Как синхронизировать два рисунка InkCanvas-es? - PullRequest
0 голосов
/ 20 декабря 2011

Я пытаюсь разработать приложение, которое показывает чертежи 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);
        }
    }

Обратите внимание, что исключение всегда ловится.

Общий вопрос здесь: как найти одинаковые штрихи / точки в коллекции, чтобы соответственно их удалить?

Ответы [ 2 ]

1 голос
/ 21 декабря 2011

Я не уверен, если вам нужно, чтобы это было так сложно, но вот решение только для разметки WPF, которое должно точно делать то, что вам нужно:

http://msdn.microsoft.com/en-us/library/system.windows.controls.inkcanvas.aspx

См. Пример после определений API. Если вы удалите три строки в разметке с помощью LayoutTransform, это должно быть именно то, что вам нужно.

Если вы хотите иметь коллекцию StrokesCollection в CodeBehind / VM, то свяжите ее как DependencyProperty или как свойство VM, и все готово.

0 голосов
/ 04 января 2012

Проблема в механизме сериализации / десериализации, используемом StrokesCollection.Когда значение double сериализуется и десериализуется, результирующее значение слегка изменяется.

Полный пример кода и ответ можно найти здесь: http://social.msdn.microsoft.com/Forums/en-AU/wpf/thread/9e1f43fa-6266-41b7-a5d0-7603f87ca58f

...