【问题标题】:WPF ContentControl Content as ContentControlWPF ContentControl 内容作为 ContentControl
【发布时间】:2016-05-05 02:12:23
【问题描述】:

难道不能有多个包含 ContentControl 的 UserControl 层吗?

我正在尝试为派生的不同模型创建视图,因此我想消除为每种对象类型重新创建视图的需要,而是提供一个 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>

同样,它有一个单独的 DependencyProperty 用于此 UserControl 上的 ContentControl,就像第一个一样。我也尝试过使用不同命名的 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 时。我添加到 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 做错了什么?我应该用不同的方法来看待这个问题吗?

【问题讨论】:

  • 我偶然发现了这个答案 - stackoverflow.com/a/5758383/2777422 到了一个类似但不同的问题。需求不同,但其中一个答案的内容最初似乎为我指明了正确的方向。它建议使用 ControlTemplate。我的问题是,为什么这可以让我深入 2 层以上?最终,这也不是完美的答案,因为我松散了 Intellisense 数据绑定,并且一旦我创建了一些 DependencyProperties 来驱动上面 UserControlLevel1 Textbloxs 中的文本值,默认值就不会显示在 ControlTemplate 中。

标签: wpf xaml user-controls nested contentcontrol


【解决方案1】:

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

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

【讨论】:

  • 这似乎有效,但我会说一些警告。如果使用了用户控件的多个实例,它们最初不会在设计器中更新,您必须重新构建项目/解决方案才能看到更改。此外,用户控制的每一层都必须具有不同名称的属性。当我去向 Level 1 和 Level 2 添加一个 relativesource 时,它​​在设计时给了我错误,并在运行时抛出了异常。我将属性的名称更改为每层唯一的名称,它似乎可以正常工作,尽管如此,我必须执行上述重建才能看到任何更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-24
  • 2021-01-25
相关资源
最近更新 更多