我有一个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个节点的曲线,如果线条相互交叉并且我更改了单个值,则处理器负载开始增加。
我将看看一些处理器采样并报告回来。
答案 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);
}
}