【问题标题】:mvvm wpf UI of InkCanvas does not updatesInkCanvas 的 mvvm wpf UI 不更新
【发布时间】:2021-12-20 20:45:25
【问题描述】:

我正在尝试在 InkCanvas 上绘图,以便绘图将显示在所有连接的用户中,反之亦然, 但 UI 不会随新图纸更新。

我在 StrokeCollected 事件中将 StrokeCollection 作为 MemoryStream 发送到服务器 OnStrokeCollected() 并从服务器接收 MemoryStream 并使用接收到的 MemoryStream CanvasStrokesReceived() 创建 StrokeCollection

这里是 ViewModel:

 class MainViewModel
    {
        public ObservableCollection<UserModel> Users { get; set; }
        public ObservableCollection<string> Messages { get; set; }
        public RelayCommand ConnectToServerCommand { get; set; }
        public RelayCommand SendMessageCommand { get; set; }
        public string UserName { get; set; }
        public string Message { get; set; }
        public StrokeCollection CanvasStrokes { get; set; }
        private Server _server;

        public MainViewModel()
        {
            Users = new ObservableCollection<UserModel>();
            Messages = new ObservableCollection<string>();
            CanvasStrokes = new StrokeCollection();
            _server = new Server();
            _server.connectedEvent += UserConnected;
            _server.msgReceivedEvent += MessageReceived;
            _server.inkStrokeReceivedEvent += CanvasStrokesReceived;
            _server.userDisconnectEvent += RemoveUser;

            ConnectToServerCommand = new RelayCommand(o => _server.ConnectToServer(UserName), o => !string.IsNullOrEmpty(UserName));
            SendMessageCommand = new RelayCommand(o => _server.SendMessageToServer(Message), o => !string.IsNullOrEmpty(Message));
        }


        public void OnStrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e)
        {
            MemoryStream _ms = new MemoryStream();
            CanvasStrokes.Save(_ms);
            _ms.Flush();

            _server.SendCanvasStrokesToServer(_ms);
        }


        private void CanvasStrokesReceived()
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                var strokes = _server.PacketReader.ReadCanvasStrokes();
                CanvasStrokes = new StrokeCollection(strokes);
            });
        }




        private void UserConnected()
        {
            var user = new UserModel
            {
                UserName = _server.PacketReader.ReadMessage(),
                UID = _server.PacketReader.ReadMessage()
            };
            if (!Users.Any(x => x.UID == user.UID))
            {
                Application.Current.Dispatcher.Invoke(() => Users.Add(user));
            }

        }

        private void MessageReceived()
        {
            var msg = _server.PacketReader.ReadMessage();
            Application.Current.Dispatcher.Invoke(() => Messages.Add(msg));

        }
        private void RemoveUser()
        {
            var uid = _server.PacketReader.ReadMessage();
            var user = Users.Where(u => u.UID == uid).FirstOrDefault();
            Application.Current.Dispatcher.Invoke(() => Users.Remove(user));
        }

    }

这是我的观点:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var mvm = new MainViewModel();
            this.DataContext = mvm;
            inkCanv.StrokeCollected += mvm.OnStrokeCollected;
            inkCanv.Strokes = mvm.CanvasStrokes;
        }
    }

这是我的 XAML:

<InkCanvas          
    x:Name="inkCanv" 
    Grid.Column="1" 
    Grid.Row="1" 
    Height="130" 
    Background="Azure"
    >
</InkCanvas>

【问题讨论】:

  • 请注意,MemoryStream 实现了 IDisposable(和 IDisposableAsync)。您应该在 using-block 的范围内定义 _ms 以自动关闭和处理流。
  • 另外,考虑调用BindingOperations.EnableCollectionSynchronization(来自每个集合的 MainViewModel 的构造函数),而不是将集合更改排队到 Dispatcher。
  • 更改作为 CanvasStrokes 等绑定源的 MainViewModel 属性必须引发 INotifyPropertyChanged.PropertyChanged 事件。

标签: c# wpf mvvm memorystream inkcanvas


【解决方案1】:

您似乎缺少更新画布。您必须明确执行此操作或使用数据绑定(推荐):

<InkCanvas Strokes="{Binding CanvasStrokes}" />

然后在MainWindow的构造函数中去掉赋值:

public MainWindow()
{
  InitializeComponent();
  var mvm = new MainViewModel();
  this.DataContext = mvm;
  inkCanv.StrokeCollected += mvm.OnStrokeCollected;
  // inkCanv.Strokes = mvm.CanvasStrokes;
}

【讨论】:

  • CanvasStrokes 还必须触发更改通知。
猜你喜欢
  • 2014-11-23
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-08
  • 2023-03-08
相关资源
最近更新 更多