代码之家  ›  专栏  ›  技术社区  ›  HS.

WPF拉丝刷性能

wpf
  •  2
  • HS.  · 技术社区  · 17 年前

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

    我尝试创建一个StreamGeometry,用它来画线,并将其指定给DrawingBrush。然而,我发现如果StreamGeometry有太多的线条,在DrawingBrush被分配到画布之后,程序会变得缓慢。

    是否存在“预渲染”网格线,并将其指定给画布?

    我试过了 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 回复  |  直到 17 年前
        1
  •  6
  •   Ifeanyi Echeruo Ifeanyi Echeruo    17 年前

    我的建议是保持原始的倒计时。你让WPF花费CPU周期和带宽来创建并将大量网格发送到渲染线程和GPU。

    画笔是一种 TileBrush .

    在DrawingImage上绘制单个网格单元,并使用TileMode、Viewbox和Viewport属性平铺网格。

        2
  •  3
  •   Community Mohan Dere    9 年前

    这个 solution offered by Ifeanyi Echeruo 对我来说非常好。然而,我也需要网格动态缩放。我没有每次重建画笔,而是使用一个xaml定义的画笔作为元素的背景,然后实现了一些钩子,以便在每次需要调整网格线大小时重新缩放画笔。

    使用元素背景属性上的LocalValueEnumerator,每次需要重新缩放时,我都会更新笔刷的“视口”属性

    <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));
      }
    }
    
        3
  •  1
  •   ligaz    17 年前

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

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