Возможно ли InvalidateVisual () для данного региона вместо всего элемента управления WPF? - PullRequest
7 голосов
/ 05 апреля 2010

У меня есть сложный элемент управления WPF, который рисует много примитивов в своем OnRender (вроде как карта). Когда небольшая его часть изменяется, мне бы хотелось только повторно выдать команды рендеринга для затронутых элементов вместо того, чтобы запускать весь OnRender. Хотя я в порядке с производительностью функции OnRender при изменении размера или чего-либо еще, этого недостаточно для выделения примитивами при наведении мыши.

В настоящее время я знаю, как заставить обновление экрана вызывать InvalidateVisual (). Невозможно отправить в грязную прямоугольную область для аннулирования.

Является ли самая низкая гранулярность композиции экрана WPF элементом пользовательского интерфейса? Нужно ли мне выполнять рендеринг примитивов в промежуточную цель, а затем использовать InvalidateVisual () для обновления на экране?

Ответы [ 3 ]

3 голосов
/ 20 декабря 2010

Если вы хотите написать пользовательские / составные элементы управления WPF, старайтесь избегать переопределения OnRender, насколько это возможно, особенно если вы планируете аннулировать его части. Намного проще использовать AddVisualChild + override VisualChildrenCount + override GetVisualChild + override Измерять и упорядочивать следующим образом (псевдокод с 2 дочерними элементами):

private void BuildMyControls()
{
  AddVisualChild(subControl1);
  AddVisualChild(subControl2);
}

protected override int VisualChildrenCount
{
  get
  {
    return 2;
  }
}

protected override Visual GetVisualChild(int index)
{
  if (index == 0) return subControl1;
  if (index == 1) return subControl2;
  return null; // should never be called in fact...
}

protected override Size MeasureCore(Size availableSize)
{
  base.Measure...
  BuildMyControls();
  .. measure them, probably call subControlX.Measure(...);
}

protected override void ArrangeCore(Rect finalRect)
{
  base.ArrangeCore(finalRect);
  ... arrange them, probably call subControlX.Arrange
}

С этим типом кода вы можете сделать недействительной только одну часть, например, subControlX.InvalidateXXX ();

0 голосов
/ 10 июня 2017

Вы не должны использовать InvalidateVisual(), если только размер вашего элемента управления не изменится, так как это вызывает довольно дорогую перестройку вашего пользовательского интерфейса.

WPF - это сохраненная система рисования. Это означает, что OnRender() лучше называть AccumulateDrawingObjects(). Это на самом деле накапливает дерево живых объектов рисования, которое должно происходить только один раз за макет. Затем он использует эти объекты для рисования вашего пользовательского интерфейса всякий раз, когда это необходимо. Чтобы изменить внешний вид части вашего пользовательского интерфейса без изменения макета, некоторые объекты (такие как DrawingGroup, RenderTargetBitmap и WriteableBitmap) можно обновить после OnRender() в любое время.

Чтобы обновить часть вашего пользовательского интерфейса позже, оберните эти команды в DrawingGroup и поместите этот объект в DrawingContext. Затем вы можете Open() и обновить его, когда захотите, и WPF автоматически перекрасит эту часть интерфейса.

Вот как это выглядит:

DrawingGroup backingStore = new DrawingGroup();

protected override void OnRender(DrawingContext drawingContext) {      
    base.OnRender(drawingContext);            

    Render(); // put content into our backingStore
    drawingContext.DrawDrawing(backingStore);
}

// I can call this anytime, and it'll update my visual drawing
// without ever triggering layout or OnRender()
private void Render() {            
    var drawingContext = backingStore.Open();
    Render(drawingContext);
    drawingContext.Close();            
}
0 голосов
/ 12 июля 2010

WPF работает не совсем так, поэтому вы не можете сделать недействительными регионы. Тем не менее, есть некоторые оптимизации, которые могут быть сделаны. Есть мера, аранжировка, а затем рендер. Если элемент управления перемещается, но то, что фактически отображается, не изменяется, вы можете указать WPF выполнить только этап аранжировки. Вы можете активировать эти недействительные изменения значений свойств зависимостей с помощью FrameworkPropertyMetadata и FrameworkPropertyMetadataOptions (http://msdn.microsoft.com/en-us/library/system.windows.frameworkpropertymetadataoptions.aspx).

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