Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多次绘制同一条线,而不丢失以前的轨迹_C#_Wpf_Visual Studio_Lines_Children - Fatal编程技术网

C# 多次绘制同一条线,而不丢失以前的轨迹

C# 多次绘制同一条线,而不丢失以前的轨迹,c#,wpf,visual-studio,lines,children,C#,Wpf,Visual Studio,Lines,Children,我正在C#中开发一个WPF,我想多次绘制一条特定的线,而不会丢失它以前的轨迹。我的网格中有10个按钮,当我按下一个按钮时,我想画一条线。对于该行,我使用var红线,每次按下按钮,它都会收到一对特定的坐标 我用这个代码来画一条线: public partial class MainWindow : Window { private Line redLine = new Line(); SolidColorBrush redBrush = new SolidColorBrush(C

我正在C#中开发一个WPF,我想多次绘制一条特定的线,而不会丢失它以前的轨迹。我的
网格中有10个
按钮
,当我按下一个按钮时,我想画一条线。对于该行,我使用var
红线
,每次按下按钮,它都会收到一对特定的坐标

我用这个代码来画一条线:

public partial class MainWindow : Window {

    private Line redLine = new Line();
    SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);

    public MainWindow()
    {
        redLine.StrokeThickness = 4;
        redLine.Stroke = redBrush;
    }

   private void button1_Click(object sender, RoutedEventArgs e) {
       redLine.X1 = 237; 
       redLine.Y1 = 382;
       redLine.X2 = 288;
       redLine.Y2 = 409;
       //draw the line
       MainGrid.Children.Add(redLine);
   }

   private void button2_Click(object sender, RoutedEventArgs e) {
       redLine.X1 = 130; 
       redLine.Y1 = 323;
       redLine.X2 = 238;
       redLine.Y2 = 690;
       //draw the line
       MainGrid.Children.Add(redLine);
   }
} 
但每次我按
按钮1
然后再按
按钮2
时,我都会出现此错误(其他按钮也会出现此错误):

错误指定的视觉对象已经是另一个视觉对象的子对象或其根对象 合成目标

我想保留这两条线,而不是为了画第二条而删除第一条线。有没有办法解决这个问题


注意我不想在每个按钮单击方法中声明每一行(整个程序中大约有11行)。

错误消息非常清楚,
已经是
MainGrid
的子元素。你不能再添加一次

在将其添加到主网格之前,您必须创建一个新的

private void button1_Click(object sender, RoutedEventArgs e)
{
    var newLine = new Line
    {
       Stroke = redBrush,
       StrokeThickness = 4,
       X1 = 237,
       Y1 = 382,
       X2 = 288,
       Y2 = 409
    };
    MainGrid.Children.Add(newLine);
}

显然,您也不再需要
私有行redLine
成员了。

我建议遵循这个示例的方法(MVVM)。它通过单击按钮随机添加新行

主窗口

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModelLine();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ViewModelLine vm = (ViewModelLine)DataContext;

        // use other information and decide how you want to add the line
        Random ran = new Random();
        vm.Models.Add(new ModelLine() { X1=ran.Next(1,600), X2= ran.Next(1, 600), Y1= ran.Next(1, 600), Y2= ran.Next(1, 600) });
    }
}
<DockPanel >
    <Button Content="Add a New Line" DockPanel.Dock="Top" Click="Button_Click"/>
    <ItemsControl DockPanel.Dock="Bottom" DataContext="{Binding}" ItemsSource="{Binding Models}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Line X1="{Binding X1}" X2="{Binding X2}" Y1="{Binding Y1}" Y2="{Binding Y2}" 
                      Stroke="Black" StrokeThickness="2"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</DockPanel> 
查看

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModelLine();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ViewModelLine vm = (ViewModelLine)DataContext;

        // use other information and decide how you want to add the line
        Random ran = new Random();
        vm.Models.Add(new ModelLine() { X1=ran.Next(1,600), X2= ran.Next(1, 600), Y1= ran.Next(1, 600), Y2= ran.Next(1, 600) });
    }
}
<DockPanel >
    <Button Content="Add a New Line" DockPanel.Dock="Top" Click="Button_Click"/>
    <ItemsControl DockPanel.Dock="Bottom" DataContext="{Binding}" ItemsSource="{Binding Models}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Line X1="{Binding X1}" X2="{Binding X2}" Y1="{Binding Y1}" Y2="{Binding Y2}" 
                      Stroke="Black" StrokeThickness="2"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</DockPanel> 

请注意,
ModelLine
可以包含笔划和厚度等其他属性。

“我不想在每个按钮单击方法中声明每一行(整个程序中大约有11行)。”为什么不呢?这可能会解决问题。是否纯粹是为了不必重复宽度/画笔等的实例化/设置?是否应该使用
CheckBox
es来显示/隐藏线条?在WPF中,您可以使用数据模板来可视化项目集合(在您的案例行中)。看见只需将新项目添加到集合中,就可以在视图中显示新行。@JamesThorpe从编程角度来看,反复声明每一行并不“正确”。我没有说这是最终解决方案,我只是想知道这是否是不重新声明它的原因。如果这是原因,还有其他方法,比如让每个按钮调用一个只提供坐标的函数,让这个函数创建直线,设置属性并添加它。@Sinatr我正在尝试创建类似于“图像地图”的东西。所以我不想要复选框,因为它将始终显示,不像按钮。我知道它是MainGrid的子元素。但是我希望避免每次都创建一条新线(正如我提到的,在10个按钮中有11条线被多次使用。难道我不能做任何其他事情吗?你不能向任何父控件添加两次一条线元素。但是,还有其他方法可以“绘制”WPF中的内容。从这里开始阅读:。感谢您的努力和时间。我将在每个单独的按钮单击方法中声明每一行