Как заставить пользовательский FrameworkElement отображать измененное содержимое? - PullRequest
2 голосов
/ 03 ноября 2011

У меня есть дерево визуалов.Главное окно имеет полноразмерный холст.Холст содержит корень некоторых пользовательских визуальных элементов.Первый пользовательский Visual (A) может расширяться и сжиматься в зависимости от того, что просматривает пользователь, которые находятся в дочерних элементах (B, которые являются DrawingVisuals).По мере изменения размера главного окна я хочу добавить или удалить дочерние элементы из A. То же самое может произойти, когда пользователь прокручивает любое направление в представлении.Когда добавляются дети (Bs), я хочу, чтобы они отображались.(Удаленные B не являются проблемой, потому что они все равно больше не видны.)

Взять сценарий: главное окно 640x480.Я изменил размер в два раза, что позволило бы отобразить больше B, которые затем добавляются в A. До сих пор я не могу получить новые добавленные B для рендеринга, даже при использовании Invalidate ??? () методов FrameworkElement.Я пробовал Invalidate ??? () в главном окне и в A, когда добавляются буквы B.(Я не имею с B, полагая, что они новые.) Похоже, что Invalidate ??? () - не тот путь.

Я нашел хак, который позволяет новым B рендериться при изменении размера,В главном окне я могу удалить A из Canvas и добавить его обратно, что заставляет дерево перерисовываться:

this.contentCanvas.Children.RemoveRange (0, contentCanvas.Children.Count);// удалить корень this.contentCanvas.Children.Add (this.CustomVisual_A);// readd root

По понятным причинам это нежелательно, особенно при прокрутке.В частности, добавляются и удаляются B, которые управляются таким образом, потому что они достаточно велики, и мне нужно уменьшить объем памяти и максимально увеличить скорость рендеринга.Вот почему я иду на неприятности.

Может ли кто-нибудь помочь мне понять, что мне нужно сделать, чтобы заставить вновь добавленные Б отображаться?Большое спасибо!

Ответы [ 2 ]

3 голосов
/ 04 ноября 2011

Я решил это.Несмотря на то, что FrameworkElement является пользовательским, вам нужно использовать стандартные методы AddVisualChild() и RemoveVisualChild() для управления своими детьми:

this.AddVisualChild(new B());
...
this.RemoveVisualChild(existingB);

Вы по-прежнему сохраняете свою собственную коллекцию B, но, похоже, если вы неиспользуйте AddVisualChild() и RemoveVisualChild() базовый FrameworkElement не видит изменения (на самом деле Panel, суперкласс Canvas).

Это может также каким-либо образом вовлечь родителя в уведомление;Точно сказать не могу.В конечном итоге эти методы управления коллекцией вызывают метод OnVisualChildrenChanged(), определенный в Panel, поэтому он должен быть реализован в A. В то время я добавляю / удаляю дочерний элемент в / из моей внутренней коллекции, а затем вызываю вbase:

protected override void OnVisualChildrenChanged(DependencyObject added, DependencyObject removed)
{
     if (added != null)
     {
        this.children.Add((B) added);
     }

     if (removed != null)
     {
        this.children.Remove((B) removed);
     }

     base.OnVisualChildrenChanged(added, removed);
}

Это вызывает некоторое внутреннее указание на необходимость рендеринга.

Я подумал, что что-то подобное должно происходить, потому что удаление A из моего пользовательского Canvas и повторное добавление A принудительнорендер.

0 голосов
/ 04 ноября 2011

Для этого есть несколько звонков ...

        element.UpdateLayout();
        element.InvalidateArrange();
        element.InvalidateMeasure();
        element.InvalidateVisual();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...