【发布时间】: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