mvvm wpf UI of InkCanvas does not updates

82 Views Asked by At

Im trying to draw on InkCanvas so the drawing will displays in all connected users and vice versa, but the UI does not updates with new drawings.

Im sending StrokeCollection as a MemoryStream in the StrokeCollected event to the server OnStrokeCollected() and receiving the MemoryStream from the server and creating StrokeCollection with the received MemoryStream CanvasStrokesReceived()

Here is 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));
        }

    }

Here is my View :

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

Here is my XAML :

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

There are 1 best solutions below

1
BionicCode On

It looks like you are missing to update the canvas. You have to do this explicitly or using data binding (recommended):

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

Then in the constructor of MainWindow remove the assignment:

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