0

Im binding and sending ink strokes as MemoryStream objects using TcpClient, TcpListener but when Im receiving the updated strokes how can I update the UI.

ViewModel : (added INotifyPropertyChanged that fired when we draw something in the View, using Signature_StrokesChanged to send the collection as a MemoryStream)

class MainViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<UserModel> Users { get; set; }
        public ObservableCollection<string> Messages { get; set; }
        public RelayCommand ConnectToServerCommand { get; set; }
        public RelayCommand SendMessageCommand { get; set; }
        public RelayCommand SendInkStrokesCommand { get; set; }
        public string UserName { get; set; }
        public string Message { get; set; }    
        private Server _server;
        public event PropertyChangedEventHandler PropertyChanged;
        public StrokeCollection Signature { get; set; }

        public MainViewModel()
        {
            Users = new ObservableCollection<UserModel>();
            Messages = new ObservableCollection<string>();
            _server = new Server();
            _server.connectedEvent += UserConnected;
            _server.msgReceivedEvent += MessageReceived;
            _server.inkStrokeReceivedEvent += InkStrokeReceived;
            _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));

            Signature = new StrokeCollection();
            Signature.StrokesChanged += Signature_StrokesChanged;
        }

        public void Signature_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
        {
            Signature = (StrokeCollection)sender;
            MemoryStream _ms = new MemoryStream();
            Signature.Save(_ms);
            _ms.Flush();

            _server.SendInkStrokesToServer(_ms);
        }
        private void InkStrokeReceived()
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                var ink = _server.PacketReader.ReadInkStroke();
                MemoryStream memoryStream = new MemoryStream(ink);
                Signature = new StrokeCollection(memoryStream);
            });
        }
        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 XAML :

<InkCanvas          
    Name="inkCanv" 
    Grid.Column="1" 
    Grid.Row="1" 
    Height="130" 
    Background="Azure"
    Strokes="{Binding Signature}"
    >
</InkCanvas>

Here is how I write them :

public void WriteInkStrokes(byte[] bytesStroke)
{
    _ms.Write(BitConverter.GetBytes(bytesStroke.Length));
    _ms.Write(bytesStroke);
}

Here is how I read them :

public byte[] ReadInkStroke()
{
    byte[] inkBuffer;
    var length = ReadInt32();
    inkBuffer = new byte[length];
    _ns.Read(inkBuffer, 0, length);

    return inkBuffer;
}

Here is how I brodacst them :

public static void BrodcastInkStrokes(byte[] inkStrokes)
{
    foreach (var user in _users)
    {
        var inkPacket = new PacketBuilder();
        inkPacket.WriteOpCode(7);
        inkPacket.WriteInkStrokes(inkStrokes);
        user.ClientSocket.Client.Send(inkPacket.GetPacketBytes());
    }
}
Kosta
  • 9
  • 2
  • Your MainViewModel implements INotifyPropertyChanged, but does not fire the PropertyChanged event for any of its properties. See e.g. here how it works: https://stackoverflow.com/a/33641274/1136211 – Clemens Nov 07 '21 at 20:32
  • @Clemens how can I convert the received bytes into an object that I could draw? – Kosta Nov 08 '21 at 08:17

0 Answers0