1

我正在创建一个在 UI 上具有绘图部分的 Signal R 应用程序,现在我正在使用 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 集线器:

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 的片段(这是一个包含所有代理的单例类):

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);
    } 
4

2 回答 2

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;
        });
    }
于 2014-02-10T20:22:53.013 回答
0

我不明白,你为什么不简单地做:

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

?

于 2014-02-04T10:07:46.393 回答