MVVM架构下WPF的InkCanvas接收远程笔迹后UI不更新问题
问题原因
- ViewModel未实现
INotifyPropertyChanged接口,CanvasStrokes属性修改后无法通知UI层更新 - View层通过后台代码直接给
InkCanvas.Strokes赋值原始集合引用,后续ViewModel替换集合实例时,View层仍指向旧的集合对象,无法感知变更
修复步骤
1. 改造ViewModel实现属性变更通知
给MainViewModel继承INotifyPropertyChanged接口,改造CanvasStrokes属性触发变更通知:
using System.ComponentModel; using System.Runtime.CompilerServices; class MainViewModel : INotifyPropertyChanged { // 实现属性变更通知基础逻辑 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 改造CanvasStrokes为带通知的属性 private StrokeCollection _canvasStrokes; public StrokeCollection CanvasStrokes { get => _canvasStrokes; set { _canvasStrokes = value; OnPropertyChanged(); } } // 其他原有代码保持不变... // 可选优化:如果是增量同步笔迹,不需要替换整个集合,直接添加新笔迹即可,性能更好 private void CanvasStrokesReceived() { Application.Current.Dispatcher.Invoke(() => { var remoteStrokes = _server.PacketReader.ReadCanvasStrokes(); // 增量添加新笔迹 foreach (var stroke in remoteStrokes) { CanvasStrokes.Add(stroke); } // 如果是全量同步逻辑,保持原有赋值写法即可: // CanvasStrokes = new StrokeCollection(remoteStrokes); }); } }
2. 修改XAML使用绑定关联Strokes属性
给InkCanvas添加Strokes绑定,不需要在后台代码手动赋值:
<InkCanvas x:Name="inkCanv" Grid.Column="1" Grid.Row="1" Height="130" Background="Azure" Strokes="{Binding CanvasStrokes}" > </InkCanvas>
3. 清理View层冗余代码
删除MainWindow后台代码中手动赋值Strokes的行:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var mvm = new MainViewModel(); this.DataContext = mvm; inkCanv.StrokeCollected += mvm.OnStrokeCollected; // 删掉这行冗余代码:inkCanv.Strokes = mvm.CanvasStrokes; } }
内容的提问来源于stack exchange,提问作者Kosta
相关产品推荐
相关产品推荐

