Улучшить скорость рисования визуального рендера - PullRequest
4 голосов
/ 18 ноября 2009

Я создаю свой собственный FrameworkElement и переопределяю VisualChildrenCount {get;} и ​​GetVisualChild (int index), возвращая свой собственный экземпляр коллекции DrawingVisual. У меня есть переопределение OnRender.

Я добавлю 20-50 DrawingVisuals в этот FrameworkElement, каждый DrawingVisual будет иметь 2000 отрезков. Логическое значение этих точек от 0 до 60000. Когда я увеличу масштаб до 1: 1, высота FrameworkElement будет равна 60000, время ожидания составит 15 минут !!

Как улучшить производительность рендеринга?

Ответы [ 2 ]

4 голосов
/ 19 ноября 2009

Для такого типа данных я бы предложил вам построить GeometryDrawing и StreamGeometry, содержащие по одной PolyLine для каждой из ваших точек. Затем объедините их все вместе в одной DrawingGroup и отобразите ее, используя один DrawingVisual.

Это будет XAML:

<DrawingVisual Drawing="{Binding CurrentDrawing}" />

и это будет код для обновления CurrentDrawing:

var group = new DrawingGroup();
foreach(var data in myData)
{
  StreamGeometry geo = new StreamGeometry();
  using(geoContext = geo.Open())
  {
    geoContext.BeginFigure(myData.StartPoint, false, false);
    geoContext.PolyLineTo(myData.AdditionalPoints, true, false);
  }
  group.Add(new GeometryDrawing
  {
    Geometry = geo,
    Pen = myData.Pen,
  });
}
CurrentDrawing = group;
...

Если ваши данные изменяются, может быть полезно создать хранилище для каждого объекта GeometryDrawing отдельно, поэтому необходимо воссоздать только те GeometryDrawings, исходные данные которых были изменены.

Обновление

Вы упоминаете в своем комментарии, что вам нужно отдельно выполнить проверку каждого из 20-50 элементов данных. В этом случае вы, вероятно, захотите использовать отдельный DrawingVisual для каждого. Для максимальной производительности вы захотите использовать RenderOpen() с DrawingContext:

IEnumerable<Visual> BuildVisuals()
{
  return
    from var data in myData
    select BuildVisualForData(data);
}

void BuildVisualForData(MyDataType data)
{
  var geo = new StreamGeometry();
  using(geoContext = geo.Open())
  {
    geoContext.BeginFigure(myData.StartPoint, false, false);
    geoContext.PolyLineTo(myData.AdditionalPoints, true, false);
  }

  var visual = new DrawingVisual();
  using(drawingContext = visual.RenderOpen())
  {
    drawingContext.DrawGeometry(null, myData.Pen, geo);
  }
  return visual;
}
0 голосов
/ 20 ноября 2009

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

Для такого типа данных я бы предложил вам построить GeometryDrawing и StreamGeometry, содержащие по одной PolyLine для каждой из ваших точек. Затем объедините их все вместе в одной DrawingGroup и отобразите ее, используя один DrawingVisual.

Это будет XAML:

<DrawingVisual Drawing="{Binding CurrentDrawing}" />

и это будет код для обновления CurrentDrawing:

var group = new DrawingGroup();
foreach(var data in myData)
{
  StreamGeometry geo = new StreamGeometry();
  using(geoContext = geo.Open())
  {
    geoContext.BeginFigure(myData.StartPoint, false, false);
    geoContext.PolyLineTo(myData.AdditionalPoints, true, false);
  }
  group.Add(new GeometryDrawing
  {
    Geometry = geo,
    Pen = myData.Pen,
  });
}
CurrentDrawing = group;
...

Если ваши данные изменяются, может быть полезно создать хранилище для каждого объекта GeometryDrawing отдельно, поэтому необходимо воссоздать только те GeometryDrawings, исходные данные которых изменились

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