WPF:动态创建的行没有出现在定义的位置

WPF: Dynamically created line does not appear at defined position

我有一个class记录一条线的起点和终点。此 class 的元素被添加到 Observable 集合中,作为我的 ItemsControl 的 ItemsSource。

这里是XAML的相关部分:

<ItemsControl Name="PathControl">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Line
                                Name="Path"
                                Stroke="Red"
                                StrokeThickness="4"
                                X1="{Binding
                                    StartCoordinates.X,
                                    Mode=TwoWay,
                                    UpdateSourceTrigger=PropertyChanged}"

                                Y1="{Binding
                                    StartCoordinates.Y,
                                    Mode=TwoWay,
                                    UpdateSourceTrigger=PropertyChanged}"
                                X2="{Binding
                                    EndCoordinates.X,
                                    Mode=TwoWay,
                                    UpdateSourceTrigger=PropertyChanged}"

                                Y2="{Binding
                                    endCoordinates.Y,
                                    Mode=TwoWay,
                                    UpdateSourceTrigger=PropertyChanged}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

这里是对应的class:

public class VisualPath: INotifyPropertyChanged
{

    public VisualPath(Point start, Point end)
    {
        this.startCoordinates = start;
        this.endCoordinates = end;
    }


    Point startCoordinates;
    public Point StartCoordinates
    {
        get
        {
            return startCoordinates;
        }

        set
        {
            startCoordinates = value;
            OnPropertyChanged();
        }
    }

    Point endCoordinates;
    public Point EndCoordinates
    {
        get
        {
            return endCoordinates;
        }

        set
        {
            endCoordinates = value;
            OnPropertyChanged();
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

这是我的主窗口的相关部分:

public MainWindow()
{          
    InitializeComponent();
    PathControl.ItemsSource = PathElements = new ObservableCollection<VisualPath>();           
}

我想创建多对按钮并用线连接它们。为此,我通过单击事件记录了两个按钮相对于网格的 absolute 位置。我将第一个按钮的位置存储在位置变量 (tempPoint) 中,当我单击第二个按钮(目标)时,应该将新行添加到集合(发生)中,第一个按钮的位置为它的 X1 和 Y1(起点)来自 tempPoint,第二个按钮的位置作为它的 X2 和 Y2(终点)。

以下是处理点击事件的方法:

private void firstButton_Click(object sender, RoutedEventArgs e)
{
    Button pathInitiator = sender as Button;
    if (pathInitiator != null)
    {
        tempPoint = pathInitiator.TranslatePoint(new Point(0, 0), MainGrid);
    }
    else
    {
        MessageBox.Show("Not Button");
    }
}

private void secondButton_Click(object sender, RoutedEventArgs e)
{
    Button pathTerminator = sender as Button;
    if (pathTerminator != null)
    {
        GeneralTransform end = pathTerminator.TransformToVisual(this);
        Point endPoint = end.Transform(new Point(0, 0));
        PathElements.Add(new VisualPath(tempPoint, endPoint));
        //PathElements.Add(new VisualPath(new Point(0, 0), new Point(200, 200)));
    }

}

虽然第一个按钮的第一个实例的位置通常被正确捕获,但线的终点总是错位,第一个按钮的任何其他实例也是如此。显示的行似乎总是翻转或移动,即使我试图在彼此之上添加多行(如注释掉的行所示),新行总是出现在前一行的下面。是我的布线不好,还是我不明白 WPF 中的线路是如何工作的?

编辑: 感谢评论,现在这对的第一个实例按应有的方式工作:

但是这对的任何其他实例都放错了地方:

如果您希望线条彼此重叠,您可以将 ItemsControlItemsPanelTemplate 设置为 Grid:

<ItemsControl Name="PathControl">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Line
                        Name="Path"
                        Stroke="Red"
                        StrokeThickness="4"
                        X1="{Binding
                            StartCoordinates.X,
                            Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged}"

                        Y1="{Binding
                            StartCoordinates.Y,
                            Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged}"
                        X2="{Binding
                            EndCoordinates.X,
                            Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged}"

                        Y2="{Binding
                            EndCoordinates.Y,
                            Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged}" />
                <TextBlock Text="{Binding EndCoordinates.Y}" />
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>