WPF C # Обновление точек Polyline в реальном времени из разных элементов UIElement - PullRequest
0 голосов
/ 08 марта 2019

Здравствуйте, я создаю полилинию с точками (elipse), которая будет обновляться при перемещении мыши пользователем после нажатия на точку, проблема в том, что точка движется, что хорошо, но не обновляет источник, который является ObservableCollection

MainWindow.xaml

<Window x:Class="sampleWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:l="clr-namespace:sampleWPF" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" Background="Green" MouseRightButtonDown="MainWindow_OnMouseRightButtonDown_">
<Window.Resources>
    <l:PointCollectionConverter x:Key="pointCollectionConverter" />
</Window.Resources>
<Grid>
    <Canvas x:Name="Canvas" Background="Yellow" Width="300" Height="300" MouseMove="UIElement_OnMouseMove">
        <Polyline x:Name="polyline" Stroke="Black" Width="300" Height="300" Points="{Binding PointCollection, Converter={StaticResource pointCollectionConverter}}" />
        <ItemsControl ItemsSource="{Binding PointCollection}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Left" Value="{Binding X}"/> <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Ellipse Width="10" Height="10" Fill="Blue" MouseLeftButtonDown="UIElement_OnMouseLeftButtonDown" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Canvas>
</Grid>

Некоторое объяснение: MainWindow_OnMouseRightButtonDown_ останавливает выбранное движение elipse.

UIElement_OnMouseMove перемещает elipse в холсте

ULelement_Out_Out_OnLementСообщение_Обозревание_откудабудет перемещено

MainWindow.xaml.cs

public partial class MainWindow: INotifyPropertyChanged {
    public MainWindow() {
        InitializeComponent();
        DataContext = this;

        PointCollection.Add(new Point(0, 0));
        PointCollection.Add(new Point(20, 20));
        PointCollection.Add(new Point(30, 30));
        PointCollection.Add(new Point(50, 50));
        PointCollection.Add(new Point(80, 80));
        PointCollection.Add(new Point(100, 100));
    }
    private ObservableCollection < Point > PointCollectionProperty {
        get;
        set;
    } = new ObservableCollection < Point > ();

    public ObservableCollection < Point > PointCollection {
        get => PointCollectionProperty;
        set {
            PointCollectionProperty = value;
            OnPropertyChanged(nameof(PointCollection));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string caller) {
        PropertyChanged ? .Invoke(this, new PropertyChangedEventArgs(caller));
    }

    Point point;
    private Point selectedPoint;
    bool activated = false;
    private Ellipse selectedEllipse;
    private ContentPresenter selectedContentPresenter;

    private void UIElement_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
        if (sender is Ellipse es) {
            Mouse.Capture(es);
            selectedEllipse = es;
            var parent = VisualTreeHelper.GetParent(selectedEllipse);
            if (parent != null) {
                selectedContentPresenter = parent as ContentPresenter;
            }

            point = Mouse.GetPosition(selectedContentPresenter);

            if (PointCollection.Any(t => t.X == Canvas.GetLeft(selectedContentPresenter) && t.Y == Canvas.GetTop(selectedContentPresenter))) {
                Debug.WriteLine("found");
                selectedPoint = PointCollection.FirstOrDefault(t =>
                    t.X == Canvas.GetLeft(selectedContentPresenter) && t.Y == Canvas.GetTop(selectedContentPresenter));
            } else {
                selectedPoint = new Point();
                Debug.WriteLine("not found");
            }

            activated = true;

        }

    }

    private void UIElement_OnMouseMove(object sender, MouseEventArgs e) {
        if (selectedContentPresenter != null) {
            if (activated) {

                double top = Canvas.GetTop(selectedContentPresenter) + Mouse.GetPosition(selectedContentPresenter).Y + point.Y;
                double left = Canvas.GetLeft(selectedContentPresenter) + Mouse.GetPosition(selectedContentPresenter).X + point.X;

                Canvas.SetTop(selectedContentPresenter, top);

                Canvas.SetLeft(selectedContentPresenter, left);
                selectedPoint.X = left;
                selectedPoint.Y = top;

                OnPropertyChanged(nameof(PointCollection));

            }
        }

    }

    private void MainWindow_OnMouseRightButtonDown_(object sender, MouseButtonEventArgs e) {
        foreach(Point child in PointCollection) {
            Debug.WriteLine(child.X + " " + child.Y);// shows original values from public MainWindow()
        }
        Mouse.Capture(null);
        activated = false;
        selectedEllipse = null;
        selectedContentPresenter = null;
    }
}
 public class PointCollectionConverter: IValueConverter {
 Debug.WriteLine("Called");
 public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) {
     if (value.GetType() == typeof(ObservableCollection < Point > ) && targetType == typeof(PointCollection)) {
         var pointCollection = new PointCollection();
         foreach(var point in value as ObservableCollection < Point > ) pointCollection.Add(point);
         return pointCollection;
     }

     return null;

 }

 public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) {
     return null;
 }
 }

Чего мне не хватает, поскольку elipse перемещается, но полилиния остается нетронутой

Редактировать: добавлен Debug.WriteLine впоказать, работает ли он, но спам отлаживается, но сбор остается прежним

Изображение, подтверждающее, что оно ломается после перемещения мыши

...