使用DataBinding绘制PolyLine

时间:2013-12-05 09:25:08

标签: c# wpf shape

我有一个Shape女巫根据中心周围的节点(角度和因子)的ObservableCollection绘制一条线。

DefiningGeometry覆盖如下所示:

            PolyLineSegment curve = new PolyLineSegment(this.Nodes.Select(NodeToPoint), true);
            PolyLineSegment bounds = new PolyLineSegment(
                new[] { new Point(0, 0), new Point(0, GeometrySize), new Point(GeometrySize, GeometrySize), new Point(GeometrySize, 0) }, false);

            PathFigureCollection figures = new PathFigureCollection(new[]
            {
                new PathFigure(NodeToPoint(this.Nodes[this.Nodes.Count - 1]), new[] { curve }, false),
                new PathFigure(new Point(0, 0), new[] { bounds }, false)
            });

            return new PathGeometry(figures, FillRule.Nonzero, null);

如果节点因子或集合发生变化,我将调用InvalidateVisual。 这是问题,如果我在窗口上有更多的这种形状,如果我经常更改因子,则交叉处理器负载弹出高达25%(在QuadCore ofc上)。

绘制经常更新的LineSegment集合的正确方法是什么? Shape是正确的组件来做到这一点。 ?也许我的方法完全错了,但我被困在这里。

编辑: 我将代码更新为以下内容:

protected override Geometry DefiningGeometry { get { return this.curveGeometry ?? EmptyBounds; } }

以及

中的PropertyChangedHandler
  private void NodePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Node node = sender as Node;
        if (node != null && this.indexMapping.ContainsKey(node) && this.indexMapping[node] != -1)
        {  
            this.UpdatePoint(node);
        }
    }

    private void UpdatePoint(Node node)
    {
        if (!this.Dispatcher.CheckAccess())
            this.Dispatcher.BeginInvoke(new Action<Node>(UpdatePoint), node);
        else
        {
            this.curve.Points[this.indexMapping[node]] = NodeToPoint(node);
            this.InvalidateVisual();    
        }
    }

如评论中所述,如果我不调用InvalidateVisual,则代码不起作用。问题依然存在,如果我添加5条总共1000个节点的曲线,如果线条相互交叉并且我更改了单个值,则处理器负载开始增加。

我将看看一些处理器采样并报告回来。

1 个答案:

答案 0 :(得分:1)

每次数据更改时都不需要创建新几何体。以下简化示例(没有MVVM)显示仅通过更改PathGeometry中PolyLineSegment中的Point来更新UI:

<Grid Background="Transparent" MouseDown="Grid_MouseDown">
    <Path Stroke="Black" StrokeThickness="2">
        <Path.Data>
            <PathGeometry x:Name="geometry"/>
        </Path.Data>
    </Path>
</Grid>

代码背后:

public partial class MainWindow : Window
{
    private PolyLineSegment segment;

    public MainWindow()
    {
        InitializeComponent();

        segment = new PolyLineSegment();
        segment.IsStroked = true;
        segment.Points.Add(new Point(100, 100));
        segment.Points.Add(new Point(200, 200));

        var figure = new PathFigure { StartPoint = new Point(0, 0) };
        figure.Segments.Add(segment);

        geometry.Figures.Add(figure);
    }

    private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
    {
        segment.Points[0] = e.GetPosition((IInputElement)sender);
    }
}