c# – WPF路径绑定到PointCollection而不更新UI
我正在尝试学习MVVM样式更新.不是那么游泳.
我不得不更新一个基于对Point Collection的更改而绘制的简单矩形. 我添加了一些TextBlock来确保Change事件被触发,但此时我有点迷失. 任何帮助赞赏: XAML: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ExampleGreg" x:Class="ExampleGreg.MainWindow" Title="MainWindow" Height="161.614" Width="324.087"> <Grid x:Name="gridUser" MouseDown="click_MouseDown" > <Canvas x:Name="MeterCanvas" Margin="14,7,30,0" Background="#FFAFAFAF" Height="35" VerticalAlignment="Top"> <Path Stroke="Black" StrokeThickness="2"> <Path.Data> <PathGeometry x:Name="geometry"/> </Path.Data> </Path> <Path Stroke="Black" StrokeThickness="2"> <Path.Data> <PathGeometry x:Name="polylinePwr"> <PathGeometry.Transform> <ScaleTransform ScaleX="{Binding ActualWidth,ElementName=MeterCanvas}" ScaleY="{Binding ActualHeight,ElementName=MeterCanvas}" /> </PathGeometry.Transform> <PathGeometry.Figures> <PathFigure IsClosed ="True" StartPoint="{Binding Path=thePoints[0]}"> <PathFigure.Segments> <PathSegmentCollection> <PolyLineSegment Points="{Binding thePoints,UpdateSourceTrigger=PropertyChanged}" /> </PathSegmentCollection> </PathFigure.Segments> </PathFigure> </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> </Canvas> <Label Content="{Binding thePoints[0]}" Margin="14,58,199.6,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> <Label Content="{Binding thePoints[1]}" Margin="14,88,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> <Label Content="{Binding thePoints[2]}" Margin="165,29.6,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> <Label Content="{Binding thePoints[3]}" Margin="165,93,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> </Grid> </Window> 主窗口: public partial class MainWindow : Window { private MainViewModel mvm; public MainWindow() { InitializeComponent(); mvm = new MainViewModel(); this.DataContext = mvm; } private void click_MouseDown(object sender,MouseButtonEventArgs e) { mvm.theText = mvm.theText + "."; mvm.ChangePoint(.4); } } 模型视图: class MainViewModel : INotifyPropertyChanged { private string _theText = "Initial"; private PointCollection _points = new PointCollection(); private PolyLineSegment segment; public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(String info) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this,new PropertyChangedEventArgs(info)); } } public MainViewModel() { ChangePoint(0.9); } public string theText { get { return _theText; } set { if (_theText != value) { _theText = value; OnPropertyChanged("theText"); } } } public PointCollection thePoints { get { return _points; } } public void ChangePoint(double x) { _points.Clear(); AddPoint(new Point(0.2,0.2)); AddPoint(new Point(0.2,0.8)); AddPoint(new Point(x,0.2)); OnPropertyChanged("thePoints"); _theText = _theText + "!"; OnPropertyChanged("theText"); } public void AddPoint(Point p) { _points.Add(p); } } 谢谢你的任何建议(工作:)) – 以下的答案 – public class PointCollectionConverter : IValueConverter { #region IValueConverter Members 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.Globalization.CultureInfo culture) { return null; //not needed } #endregion } 并将ModelView更改为使用Observable Collection … class MainViewModel : INotifyPropertyChanged { private string _theText = "Initial"; private ObservableCollection<Point> _points; public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(String info) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this,new PropertyChangedEventArgs(info)); } } public MainViewModel() { _points = new ObservableCollection<Point>(); _points.Add(new Point(0.2,0.2)); _points.Add(new Point(0.2,0.8)); } public string theText { get { return _theText; } set { if (_theText != value) { _theText = value; OnPropertyChanged("theText"); } } } public ObservableCollection<Point> thePoints { get { return _points; } } double xAdder = 0; double y = 0.0; public void ChangePoint(double x) { y = y + .1; if (y > .9) { y = .1; xAdder += .1; } _points.Add(new Point(x+xAdder,y)); OnPropertyChanged("thePoints"); _theText = _theText + "!"; OnPropertyChanged("theText"); } } 并更新了XAML: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ExampleGreg" x:Class="ExampleGreg.MainWindow" Title="MainWindow" Height="161.614" Width="324.087"> <Window.Resources> <local:PointCollectionConverter x:Key="pointCollectionConverter"/> </Window.Resources> <Grid x:Name="gridUser" MouseDown="click_MouseDown" > <Canvas x:Name="MeterCanvas" Margin="14,0" Background="#FFAFAFAF" Height="35" VerticalAlignment="Top"> <Path Stroke="Black" StrokeThickness="2"> <Path.Data> <PathGeometry x:Name="geometry"/> </Path.Data> </Path> <Path Stroke="Black" StrokeThickness="2"> <Path.Data> <PathGeometry x:Name="polylinePwr"> <PathGeometry.Transform> <ScaleTransform ScaleX="{Binding ActualWidth,ElementName=MeterCanvas}" /> </PathGeometry.Transform> <PathGeometry.Figures> <PathFigure StartPoint="{Binding Path=thePoints[0],Converter={StaticResource pointCollectionConverter}}"> <PathFigure.Segments> <PathSegmentCollection> <PolyLineSegment Points="{Binding thePoints,Converter={StaticResource pointCollectionConverter}}" /> </PathSegmentCollection> </PathFigure.Segments> </PathFigure> </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> </Canvas> <Label Content="{Binding thePoints[0]}" Margin="14,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> <Label Content="{Binding thePoints[1]}" Margin="14,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> <Label Content="{Binding thePoints[2]}" Margin="165,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> <Label Content="{Binding thePoints[3]}" Margin="165,0" VerticalAlignment="Top" Height="30" BorderThickness="1"/> </Grid> 鉴于IValueConverter创建了一个新的PointCollection,我不确定我是否会获得任何性能提升.每个ObservableCollection都会被更改. 感谢大家帮助我完成这项工作.我希望将完整的代码粘贴为有效,如果有其他人遇到同样的事情. 编辑#2 – 在Observable w / IValueConverter与Copying PointCollection对新PointCollection进行基准测试后,Point Collection看起来更快: // Option 2 - WAY Faster. // Just Use a Points Collection,copy it,and add a point. public void AddPoint2(Point pt) { PointCollection pc = new PointCollection(_points2); pc.Add(new Point(pt.X,pt.Y)); _points2 = pc; OnPropertyChanged("thePoints2"); } 来自 // 5000 point sinwave for testing foreach (Point pt in sinWave) mvm.AddPoint2(pt); x++; 如果有更好的方式,评论赞赏. 解决方法
尝试替换属性,而不是清除重新填充它.
public void ChangePoint(double x) { var newPoints = new PointCollection(); newPoints.Add(new Point(0.2,0.2)); newPoints.Add(new Point(0.2,0.8)); newPoints.Add(new Point(x,0.2)); OnPropertyChanged("thePoints"); _theText = _theText + "!"; OnPropertyChanged("theText"); } 如果对象引用相同,绑定似乎有时会忽略“PropertyChanged”事件. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |