开发者

WPF element that dynamically creates (encapsulated) children at runtime

I want to create a WPF element that, at runtime, is in full control of its child elements -- adding and removing child UI when its properties change. Something a bit like what ItemsControl does when you modify its ItemsSource property, though in my case there'll only be one child.

This will be a view container for MVVM -- when you give it a Model or a ViewModel, it will magically create the correct View and wire everything up. There's no need for my view conta开发者_如何学编程iner to be templatable (since it creates user-defined views, which are UserControls and have their own templates), and I'd prefer that it encapsulate as much as possible. I could probably do this easily by descending from something like Grid, and adding child controls when my own properties change; but Grid publicly exposes its collection of child elements and lets anyone add and remove stuff.

Which WPF class should I descend from for maximum encapsulation, and how do I add child elements to it at runtime?

Based on my understanding of the docs, I tried using FrameworkElement and AddVisualChild, just to see if I could create child controls at runtime. I'm not clear on whether the AddLogicalChild is necessary, but I put it in just in case:

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;
    }
}

When I put a ViewContainer into a Window, and run this, I expect to see a TextBlock saying "ViewContainer". But instead, I just see a blank window. So obviously I'm missing something.

How can I fix the above code so that the "child" control does appear at runtime, but isn't exposed for others to mess with (any more than can be avoided)?


To answer your specific question, you'll also need to override GetVisualChild and VisualChildrenCount properties to enable your child element to be displayed.


Have you thought about taking advantage of WPF's support for implicit DataTemplates?

The way I have handled a requirement similar to yours is by using a ContentControl. I bind the Content property to my ViewModel. I then make sure that in Resource Dictionaries referenced somewhere in the tree above the ContentControl I have DataTemplates defined for all the types of ViewModels that might be assigned to the Content Property.

This way WPF takes care of wiring up the correct view for my ViewModel.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜