如何在InkCanvas / StrokeCollection上以编程方式编写EraseByPoint?

时间:2014-01-31 19:59:40

标签: c# wpf signalr inkcanvas

我正在创建一个Signal R应用程序,在UI上有一个绘图部分,现在我正在使用WPF客户端,但最终还是会有一个MVC和Android客户端。

绘图事件处理得很完美,但是使用我处理删除的方法,其他客户端最终会删除整个笔划而不是仅删除点。

执行擦除的客户端正在使用EraseByPoint方法,一切正常。

绘图更新详细信息通过DrawingDto传递给客户端:

public class DrawingDto
{
    public DrawingDto()
    {
        NewStrokes = new List<StrokeDto>();
        DeletedStrokes = new List<StrokeDto>();
    }
    public IList<StrokeDto> NewStrokes { get; set; }
    public IList<StrokeDto> DeletedStrokes { get; set; }
}

public class StrokeDto
{
    public StrokeDto()
    {
        Points = new List<Point>();
    }
    public IList<Point> Points { get; set; }
}

代码处理器添加新笔划并尝试删除已删除的笔划:

private void OnUpdateDrawing(DrawingDto drawing)
    {
        Execute.OnUiThread(() =>
        {
            (Strokes as INotifyCollectionChanged).CollectionChanged -= StrokesOnCollectionChanged;
            var strokeCollection = new StrokeCollection();
            foreach (var newStroke in drawing.NewStrokes)
            {
                var pointCollection = new StylusPointCollection();
                foreach (var point in newStroke.Points)
                {
                    pointCollection.Add(new StylusPoint(point.X, point.Y));
                }
                strokeCollection.Add(new Stroke(pointCollection));
            }
            Strokes.Add(strokeCollection);

            foreach (var deletedStroke in drawing.DeletedStrokes)
            {
                Strokes.Erase(deletedStroke.Points.Select(x=> new System.Windows.Point(x.X, x.Y)), new RectangleStylusShape(1,1));
            }
            (Strokes as INotifyCollectionChanged).CollectionChanged += StrokesOnCollectionChanged;
        });
    }

在此代码中,Execute.OnUiThread使用调度程序来调用操作,正在删除事件侦听器以避免向服务器发送递归更新。

最后,代码创建了Dto:

public async void StrokesOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
    {
        var dto = new DrawingDto();
        if (args.NewItems !=null)
        {
            foreach (Stroke newStroke in args.NewItems)
            {
                dto.NewStrokes.Add(new StrokeDto { Points = newStroke.StylusPoints.Select(x => new Point((int)x.X, (int)x.Y)).ToList() });
            }
        }

        if (args.OldItems!= null)
        {
            foreach (Stroke deletedStroke in args.OldItems)
            {
                dto.DeletedStrokes.Add(new StrokeDto { Points = deletedStroke.StylusPoints.Select(x => new Point((int)x.X, (int)x.Y)).ToList() });
            }
        }


        await _signalRManager.UpdateDrawing(dto);
    }

编辑:这里要求的是信号r代码。

Signal R Hub:

public class DrawingHub : Hub
{
    public void UpdateDrawing(DrawingDto drawing)
    {
        Clients.Others.UpdateDrawing(drawing);
    }
}

向Hub发送更新的客户端代码:

public async void StrokesOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
    {
        var dto = new DrawingDto();
        if (args.NewItems !=null)
        {
            foreach (Stroke newStroke in args.NewItems)
            {
                dto.NewStrokes.Add(new StrokeDto { Points = newStroke.StylusPoints.Select(x => new Point((int)x.X, (int)x.Y)).ToList() });
            }
        }

        if (args.OldItems!= null)
        {
            foreach (Stroke deletedStroke in args.OldItems)
            {
                dto.DeletedStrokes.Add(new StrokeDto { Points = deletedStroke.StylusPoints.Select(x => new Point((int)x.X, (int)x.Y)).ToList() });
            }
        }


        await _signalRManager.UpdateDrawing(dto);
    }
来自SignalRManager的

Snippet(这是一个包含所有代理的单例类):

public async Task UpdateDrawing(DrawingDto dto)
    {
        await DrawingProxy.Invoke("UpdateDrawing", dto);
    }

public event Action<DrawingDto> UpdateDrawingEvent; 


private void OnUpdateDrawing(DrawingDto drawing)
    {
        if(UpdateDrawingEvent != null) UpdateDrawingEvent.Invoke(drawing);
    } 

2 个答案:

答案 0 :(得分:1)

好的,这里的问题是对InkCanvas如何处理擦除的误解。

StrokesOnCollectionChanged处理程序中,OldItems集合将包含橡皮擦触及的任何笔划的全部内容,而NewItems将包含在橡皮擦击中原始内容时分割的新笔划。

因为在OnUpdateDrawing代码中首先处理新项目然后删除旧项目,我实际上正在删除刚刚添加的新笔画。

现在通过处理删除的笔划,首先一切都按预期工作,代码片段:

private void OnUpdateDrawing(DrawingDto drawing)
    {
        Execute.OnUiThread(() =>
        {
            (Strokes as INotifyCollectionChanged).CollectionChanged -= StrokesOnCollectionChanged;
            var strokeCollection = new StrokeCollection();

            foreach (var deletedStroke in drawing.DeletedStrokes)
            {
                Strokes.Erase(deletedStroke.Points.Select(x => new System.Windows.Point(x.X, x.Y)), new RectangleStylusShape(0.01, 0.01));
            }

            foreach (var newStroke in drawing.NewStrokes)
            {
                var pointCollection = new StylusPointCollection();
                foreach (var point in newStroke.Points)
                {
                    pointCollection.Add(new StylusPoint(point.X, point.Y));
                }
                strokeCollection.Add(new Stroke(pointCollection));
            }
            Strokes.Add(strokeCollection);

            (Strokes as INotifyCollectionChanged).CollectionChanged += StrokesOnCollectionChanged;
        });
    }

答案 1 :(得分:0)

我不明白,你为什么不这样做:

 foreach (var deletedStroke in drawing.DeletedStrokes)
    Strokes.Remove(deletedStroke);