WPF: динамически созданная линия не отображается в определенной позиции

У меня есть класс, который записывает начальную и конечную точки линии. Элементы этого класса добавляются в Observable Collection, которая служит источником ItemsSource моего ItemsControl.

Вот соответствующая часть 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>

И вот соответствующий класс:

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));
    }
}

Это соответствующая часть моего MainWindow:

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

Я хотел бы создать несколько пар кнопок и соединить их линиями. Для этого я записываю абсолютное положение двух кнопок относительно сетки с событием клика. Я сохраняю положение первой кнопки в переменной Position (tempPoint), и когда я нажимаю на вторую кнопку (цель), в коллекцию должна быть добавлена ​​новая строка (что происходит) с позицией 1-й кнопки как его 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?

EDIT: Благодаря комментариям, теперь первый экземпляр пары работает так, как должен:

Края кнопок соединены линией, как и ожидалось

Но любые другие экземпляры пары неуместны: Пара не подключена, хотя используется тот же метод


person rTECH    schedule 08.02.2017    source источник
comment
У вас есть тип в привязке Y2. endCoordinates.Y должен быть EndCoordinates.Y с большой буквы E. Помимо этого, в чем конкретно заключается ваша проблема? Каков ожидаемый результат и результат, который вы видите?   -  person mm8    schedule 08.02.2017
comment
Спасибо, это немного помогло: теперь мой первый экземпляр пар работает как надо. Но последующие экземпляры неуместны. Это может быть связано с тем, что моя переменная Point не возвращается в исходное состояние (0, 0), хотя я пробовал это безрезультатно.   -  person rTECH    schedule 08.02.2017
comment
Обратите внимание, что установка Mode=TwoWay (и, следовательно, также UpdateSourceTrigger=PropertyChanged) не имеет смысла для привязок X1, Y1, X2 и Y2. Кроме того, вместо Line вам, вероятно, лучше использовать Path с LineGeometry, где вы можете напрямую связать свойства StartPoint и EndPoint.   -  person Clemens    schedule 08.02.2017
comment
Триггер обновления и привязка TwoWay предназначены для будущей функции, в которой конец строк будет следовать за каждым перетаскиванием кнопок. Что касается желаемого эффекта, я редактирую свой вопрос через минуту.   -  person rTECH    schedule 08.02.2017


Ответы (1)


Если вы хотите, чтобы строки заканчивались друг над другом, вы можете установить ItemsPanelTemplate из ItemsControl на 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>
person mm8    schedule 08.02.2017
comment
Ну, это был просто способ проверить, работает ли мой xaml или нет, так что я не собираюсь нагромождать строки таким образом :) - person rTECH; 08.02.2017
comment
Тогда может быть идеей изложить свою идею...? - person mm8; 08.02.2017
comment
Я хотел бы создать несколько пар кнопок и соединить их линиями. Разве это недостаточно описательно с приложенными изображениями? :) - person rTECH; 08.02.2017
comment
Нет, это явно не так. Предоставьте минимальный, полный и проверяемый пример, включая все соответствующие фрагменты кода: stackoverflow.com/help/mcve - person mm8; 08.02.2017
comment
Я буду, но сначала я хотел бы знать, есть ли что-то неправильное в том, как я подхожу к проблеме. В любом случае вернуть точно такие же и проверяемые условия было бы сложно, поскольку у меня есть несколько привязок, и то, что я называю кнопкой для простоты, на самом деле является элементом нескольких слоев, привязанным к другой Observable Collection (которая, тем не менее, работает без Новая функция). Поэтому я иду дальше, только если моя основная идея не ошибочна. Но спасибо, что указали на это. - person rTECH; 08.02.2017