如何同步两个inkcanvas绘图
本文关键字:两个 inkcanvas 绘图 同步 何同步 | 更新日期: 2023-09-27 18:18:37
我正在尝试开发一个应用程序,在远程主机上显示WPF InkCanvas绘图。基本上,它将本地InkCanvas与多个远程主机同步。我已订阅StrokesChanged
事件:
this.DrawingCanvas.Strokes.StrokesChanged += this.Strokes_StrokesChanged;
和处理程序
private void Strokes_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
{
if (e.Added != null && e.Added.Count > 0)
{
this.StrokeSynchronizer.SendAddedStroke(e.Added);
}
if (e.Removed != null && e.Removed.Count > 0)
{
this.StrokeSynchronizer.SendRemovedStroke(e.Removed);
}
}
当我绘制新曲线时,事件只调用一次。远程主机通过调用this.RemoteInkCanvas.Strokes.Add(addedStrokes)
正确绘制。
当我通过InkCanvasEditingMode.EraseByStroke
擦除曲线时,事件也被调用一次,远程主机成功使用this.RemoteInkCanvas.Strokes.Remove(removedStrokes)
。
问题来了!
当this.DrawingCanvas.EditingMode
是InkCanvasEditingMode.EraseByPoint
时,事件调用一次,但有两个集合(添加和删除)。这会导致远程主机发疯。下面是擦除笔划的远程主机代码:
private StrokeCollection FindStrokesInLocalCollection(StrokeCollection receivedCollection)
{
var localStrokes = new StrokeCollection();
foreach (var erasedStroke in receivedCollection)
{
var erasedPoints = erasedStroke.StylusPoints;
foreach (var existentStoke in this.RemoteInkCanvas.Strokes)
{
var existentPoints = existentStoke.StylusPoints;
if (erasedPoints.SequenceEqual(existentPoints))
{
localStrokes.Add(existentStoke);
}
}
}
return localStrokes;
}
private void RemoteStrokeRemoved(StrokeCollection strokes)
{
try
{
// Simple this.RemoteInkCanvas.Strokes.Remove(strokes)
// does not work, because local and remote strokes are different (though equal) objects.
// Thus we need to find same strokes in local collection.
var strokesToRemove = this.FindStrokesInLocalCollection(strokes);
if (strokesToRemove.Count != strokes.Count)
{
Logger.Warn(string.Format(
"Whiteboard: Seems like remotely removed strokes were not found in local whiteboard. Remote count {0}, local count {1}.",
strokes.Count,
strokesToRemove.Count));
}
this.RemoteInkCanvas.Strokes.Remove(strokesToRemove);
}
catch (Exception ex)
{
Logger.Error("Whiteboard: Can not remove some strokes received from remote host.", ex);
}
}
请注意,异常总是被捕获的。
这里的一般问题:如何在集合中找到相同的笔画/点,以便相应地删除它们?
我不确定您是否需要这么复杂,但这里有一个仅WPF标记的解决方案,它应该正好满足您的需要:
http://msdn.microsoft.com/en-us/library/system.windows.controls.inkcanvas.aspx参见API定义后面的示例。如果您使用LayoutTransform删除标记中的三行,它应该正是您所需要的。
如果你想在CodeBehind/VM中拥有StrokesCollection,那么将其绑定为DependencyProperty或作为VM Property,然后你就可以设置了。
问题出在StrokesCollection使用的序列化/反序列化机制上。当对double
值进行序列化和反序列化时,结果值略有不同。
完整的代码示例和答案可以在这里找到:http://social.msdn.microsoft.com/Forums/en-AU/wpf/thread/9e1f43fa-6266-41b7-a5d0-7603f87ca58f