WPF DrawingBrush性能

时间:2008-11-23 10:47:11

标签: wpf

我需要在画布的背景上绘制网格线,并在其上放置其他控件。

我尝试创建StreamGeometry,使用它绘制线条,并将其分配给DrawingBrush。但是我发现如果StreamGeometry有太多行,那么在将DrawingBrush分配给Canvas后,程序会变得迟缓。

是否有'预渲染'网格线并将其分配给Canvas?

我尝试Freeze()画笔和几何图形,但这似乎不起作用。我还有其他选择吗?

这是我的代码:

public void RenderGrid()
{
    this.UpdateGrid();
    Pen grid_pen = new Pen(Brushes.Blue, 0.1);
    StreamGeometry sg = new StreamGeometry();

    DrawingBrush b = new DrawingBrush();
    GeometryDrawing gd = new GeometryDrawing();
    gd.Geometry = sg;
    gd.Pen = grid_pen;
    b.Drawing = gd;

    StreamGeometryContext ctx = sg.Open();
    foreach (double d in this.VerticalGrids)
    {

        ctx.BeginFigure(new Point(d, 0), true, false);
        ctx.LineTo(new Point(d, this.RenderSize.Height), true,false);
    }
    foreach (double d in this.HorizontalGrids)
    {

        ctx.BeginFigure(new Point(0, d), true, false);
        ctx.LineTo(new Point(this.RenderSize.Width, d),true, false);
    }
    ctx.Close();
    sg.Freeze();
    gd.Freeze();

    b.Freeze();
    this.Background = b;
}

3 个答案:

答案 0 :(得分:6)

我的建议是保持原始数量下降。您正在使WPF花费CPU周期和带宽来创建并将大量网格发送到渲染线程和GPU。

DrawingBrush是TileBrush

将一个网格单位绘制到DrawingImage上,并使用TileMode,Viewbox和Viewport属性来平铺网格。

答案 1 :(得分:3)

solution offered by Ifeanyi Echeruo非常适合我。但是,我还需要网格动态扩展。我不是每次重建画笔,而是使用单个xaml定义的画笔作为元素的背景,然后在每次需要调整网格线的大小时,实现一些钩子来重新缩放画笔。

在元素的Background属性上使用LocalValueEnumerator,每次需要重新缩放时我都会更新画笔的“Viewport”属性

<DrawingBrush x:Key="MyBrush" TileMode="Tile" Stretch="Fill" 
  Viewport="0,0,250,250" ViewportUnits="Absolute">


LocalValueEnumerator props = Background.GetLocalValueEnumerator();
while (props.MoveNext())
{
  DependencyProperty prop = props.Current.Property;
  if ((prop.Name == "Viewport") && (!prop.ReadOnly))
  {
    Background.SetValue(prop, new Rect(0, 0, m_ColumnWidth, m_RowHeight));
  }
}

答案 2 :(得分:1)

一种解决方案是在面板上覆盖OnRender(DrawingContext dc)方法并在其中绘制线条。

另一种选择是拥有一个绘制线条的轻量级视觉元素。应将此元素添加到面板的可视树中。当ShowGridLines属性设置为true时,标准WPF网格控件使用类似的方法在行和列之间绘制线条。