WPF ContentControl内容为ContentControl

时间:2016-05-03 19:11:51

标签: wpf xaml user-controls nested contentcontrol

是否不可能有多层UserControl包含ContentControl?

我正在尝试为派生的不同模型创建视图,因此我想消除为每个对象类型重新创建视图的需要,而是提供ContentControl或ContentPresenter来注入“休息”的观点“。但是,我只能用这种方法深入一级。

这是一个简化的例子。(我删除了一些xmlns)。在我的情况下,我正在处理更复杂的视图,并试图消除多个地方的重复代码,关注以后的更改。

我有一个Base UserControl,我们称之为UserControlLevel1

<UserControl x:Class="ContentControlNesting.UserControlLevel1"
             x:Name="userControlLevel1"
             xmlns:local="clr-namespace:ContentControlNesting">
    <StackPanel>
        <TextBlock Text="UserControlLevel1ContentTop"/>
        <ContentControl Content="{Binding ElementName=userControlLevel1, Path=ChildContent}"/>
        <TextBlock Text="UserControlLevel2ContentBottom"/>
    </StackPanel>
</UserControl>

UserControl上有以下DependencyProperty

namespace ContentControlNesting
{
    public partial class UserControlLevel1 : UserControl
    {
        public UserControlLevel1()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty ChildContentProperty = DependencyProperty.Register("ChildContent", typeof(UIElement), typeof(UserControlLevel1), new PropertyMetadata(null));

        public UIElement ChildContent
        {
            get { return (UIElement)GetValue(ChildContentProperty); }
            set { SetValue(ChildContentProperty, value); }
        }
    }
}

ContentControl将在以下名为UserControlLevel2的UserControl中使用。这个UserControl工作正常,就像我期望的那样。或者更确切地说,UserControlLevel1在UserControlLevel2中正常工作。

<UserControl x:Class="ContentControlNesting.UserControlLevel2"
             x:Name="userControlLevel2"
             xmlns:local="clr-namespace:ContentControlNesting">
    <local:UserControlLevel1>
        <local:UserControlLevel1.ChildContent>
            <StackPanel>
                <TextBlock Text="UserControlLevel2ContentTop"/>
                <ContentControl Content="{Binding ElementName=userControlLevel2, Path=ChildContent}"/>
                <TextBlock Text="UserControlLevel2ContentBottom"/>
            </StackPanel>
        </local:UserControlLevel1.ChildContent>
    </local:UserControlLevel1>
</UserControl>

同样,它在此UserControl上的ContentControl有一个DependencyProperty,就像第一个一样。我也尝试使用不同名称的DependencyProperties。

namespace ContentControlNesting
{
    public partial class UserControlLevel1 : UserControl
    {
        public UserControlLevel1()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty ChildContentProperty = DependencyProperty.Register("ChildContent", typeof(UIElement), typeof(UserControlLevel1), new PropertyMetadata(null));

        public UIElement ChildContent
        {
            get { return (UIElement)GetValue(ChildContentProperty); }
            set { SetValue(ChildContentProperty, value); }
        }
    }
}

好的,所以在这一点上,一切似乎都运转正常。我在UserControlLevel1的ContentControl中添加了其他内容,我在UserControlLevel2 UserControl中添加了另一个ContentControl。

问题是当我尝试引入UserControl或我的MainWindow的第3层时。我添加到UserControlLevel2的ContentControl的任何内容都不会出现。

<Window x:Class="ContentControlNesting.MainWindow"
        xmlns:local="clr-namespace:ContentControlNesting"
        Title="MainWindow" Height="200" Width="300">
    <local:UserControlLevel2>
        <local:UserControlLevel2.ChildContent>
            <StackPanel>
                <TextBlock Text="Main Window Content Text"/>
            </StackPanel>
        </local:UserControlLevel2.ChildContent>
    </local:UserControlLevel2>
</Window>

我是否尝试做一些不可能的事情?或者我在使用ContentControl和DependencyProperties做错了什么?我应该用不同的方法来看待这个吗?

1 个答案:

答案 0 :(得分:0)

有可能。系统无法解析ElementName中的Binding。解决方案是使用相对绑定。只需在UserControlLevel2中替换以下行,即可完成:

<ContentControl Content="{Binding Path=ChildContent, RelativeSource={RelativeSource AncestorType={x:Type local:UserControlLevel2}}}"/>