我正在尝试学习MVVM样式更新.不是那么游泳.
我不得不更新一个基于对Point Collection的更改而绘制的简单矩形.
在初始化时,UI更新,但在对Point Collection进行简单更改后,UI中的路径不会更新.
我添加了一些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); } }
谢谢你的任何建议(工作:))
– 以下的答案 –
我添加了一个IValueConverter类:
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 …
更新了ModelView:
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”事件.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。