WPF DrawingBrush производительность - PullRequest
2 голосов
/ 23 ноября 2008

Мне нужно нарисовать линии сетки на фоне холста, на котором будут размещены другие элементы управления.

Я попытался создать StreamGeometry, используя его для рисования линий, и получить его, назначенный DrawingBrush. Однако я считаю, что если StreamGeometry имеет слишком много строк, программа становится вялой после назначения DrawingBrush для 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 ]

6 голосов
/ 24 ноября 2008

Мой совет - вести примитивный отсчет. Вы заставляете WPF тратить циклы ЦП и пропускную способность, создавая и отправляя эту массивную сетку в поток рендеринга и графический процессор.

DrawingBrush - это TileBrush .

Нарисуйте одну единицу сетки на DrawingImage и используйте свойства TileMode, Viewbox и Viewport для разбиения сетки на ячейки.

3 голосов
/ 08 января 2009

Решение , предложенное Ifeanyi Echeruo , сработало для меня очень хорошо. Однако мне также нужно было динамически масштабировать сетку. Вместо того, чтобы перестраивать кисть каждый раз, я использовал одну заданную xaml кисть для фона моего элемента, а затем реализовал несколько крючков для изменения масштаба этой кисти каждый раз, когда необходимо изменить размер линий сетки.

Используя LocalValueEnumerator в свойстве Background элемента, я обновляю свойство кисти "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));
  }
}
1 голос
/ 23 ноября 2008

Одним из решений является переопределение метода OnRender (DrawingContext dc) на панели и рисование линий там.

Другой вариант - иметь легкий визуальный элемент, который рисует линии. Этот элемент должен быть добавлен в визуальное дерево панели. Стандартный элемент управления WPF Grid использует аналогичный подход для рисования линий между строками и столбцами, если для свойства ShowGridLines установлено значение true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...