4

我想创建一个 WPF 元素,该元素在运行时完全控制其子元素——在其属性更改时添加和删除子 UI。有点像 ItemsControl 在您修改 ItemsSource 属性时所做的事情,尽管在我的情况下只有一个孩子。

这将是 MVVM 的视图容器——当你给它一个模型或视图模型时,它会神奇地创建正确的视图并将所有内容连接起来。我的视图容器不需要模板化(因为它创建了用户定义的视图,这些视图是 UserControls 并且有自己的模板),我希望它尽可能地封装。我可以很容易地做到这一点,方法是从像 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 放入 Window 并运行它时,我希望看到一个 TextBlock 说“ViewContainer”。但相反,我只看到一个空白窗口。所以很明显我错过了一些东西。

如何修复上面的代码,以便“子”控件确实在运行时出现,但不会暴露给其他人乱搞(不能避免)?

4

2 回答 2

6

要回答您的特定问题,您还需要覆盖GetVisualChildVisualChildrenCount属性以使您的子元素能够显示。

于 2010-06-23T15:50:03.657 回答
0

您是否考虑过利用 WPF 对隐式 DataTemplates 的支持?

我处理与您类似的要求的方式是使用ContentControl. 我将Content属性绑定到我的 ViewModel。然后,我确保在 ContentControl 上方树中某处引用的资源字典中,我为所有可能分配给 Content 属性的 ViewModel 类型定义了 DataTemplates。

这样,WPF 负责为我的 ViewModel 连接正确的视图。

于 2010-06-23T15:36:12.437 回答