您好,我正在创建带有点(椭圆)的折线,该点将在用户单击点后通过用户鼠标移动来更新,问题是点在移动,这很好,但不会更新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_停止选定的椭圆移动。
UIElement_OnMouseMove在画布中移动椭圆
UIElement_OnMouseLeftButtonDown选择将要移动的椭圆
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;
}
}
由于椭圆确实移动但折线保持不变,我在这里缺少的东西
编辑:添加了Debug.WriteLine以显示其是否正常运行,但垃圾邮件调试但收集仍保持不变