Элемент WPF, который динамически создает (инкапсулирует) дочерние элементы во время выполнения - PullRequest
4 голосов
/ 23 июня 2010

Я хочу создать элемент WPF, который во время выполнения полностью контролирует свои дочерние элементы - добавляя и удаляя дочерний интерфейс при изменении его свойств. Нечто похожее на то, что делает ItemsControl при изменении его свойства ItemsSource, хотя в моем случае будет только один дочерний элемент.

Это будет контейнер представления для MVVM - когда вы дадите ему Model или ViewModel, он волшебным образом создаст правильный View и соединит все. Нет необходимости, чтобы мой контейнер вида был изменяемым (поскольку он создает определяемые пользователем представления, которые являются пользовательскими элементами управления и имеют свои собственные шаблоны), и я бы предпочел, чтобы он как можно больше инкапсулировал. Я мог бы легко сделать это, спустившись с чего-то вроде Grid, и добавив дочерние элементы управления, когда мои собственные свойства изменятся; но Grid публично предоставляет свою коллекцию дочерних элементов и позволяет любому добавлять и удалять вещи.

Из какого класса WPF мне следует спуститься для максимальной инкапсуляции и как добавить к нему дочерние элементы во время выполнения?

Основываясь на своем понимании документов, я попытался использовать FrameworkElement и AddVisualChild, просто чтобы посмотреть, смогу ли я создать дочерние элементы управления во время выполнения. Мне не ясно, нужен ли AddLogicalChild, но я добавил его на всякий случай:

public class ViewContainer : FrameworkElement {
    private TextBlock _child;

    public ViewContainer() {
        _child = new TextBlock { Text = "ViewContainer" };
        AddLogicalChild(_child);
        AddVisualChild(_child);
        InvalidateMeasure();
    }

    public object Content { get; set; }

    protected override Size ArrangeOverride(Size finalSize) {
        _child.Arrange(new Rect(finalSize));
        return finalSize;
    }
    protected override Size MeasureOverride(Size availableSize) {
        _child.Measure(availableSize);
        return _child.DesiredSize;
    }
}

Когда я помещаю ViewContainer в окно и запускаю его, я ожидаю увидеть TextBlock с надписью «ViewContainer». Но вместо этого я просто вижу пустое окно. Очевидно, я что-то упускаю.

Как я могу исправить вышеприведенный код, чтобы «дочерний» элемент управления появлялся во время выполнения, но не был доступен для других пользователей (больше, чем можно избежать)?

Ответы [ 2 ]

6 голосов
/ 23 июня 2010

Чтобы ответить на ваш конкретный вопрос, вам также необходимо переопределить свойства GetVisualChild и VisualChildrenCount , чтобы включить отображение дочернего элемента.

0 голосов
/ 23 июня 2010

Задумывались ли вы о том, чтобы воспользоваться поддержкой WPF для неявных шаблонов данных?

Я выполнил требование, аналогичное вашему, с помощью ContentControl.Я связываю свойство Content с моей моделью представления.Затем я проверяю, что в ресурсных словарях, на которые есть ссылки в дереве над ContentControl, у меня есть DataTemplates, определенные для всех типов ViewModels, которые могут быть назначены свойству Content.правильный вид для моей ViewModel.

...