如何同步两个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.EditingModeInkCanvasEditingMode.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);
        }
    }

请注意,异常总是被捕获的。

这里的一般问题:如何在集合中找到相同的笔画/点,以便相应地删除它们?

如何同步两个inkcanvas绘图

我不确定您是否需要这么复杂,但这里有一个仅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