【问题标题】:How to Get ContentControl Children Within Template如何在模板中获取 ContentControl 子项
【发布时间】:2026-02-04 17:05:01
【问题描述】:

我花了几个小时搜索和测试,但无法让它工作。我想要一个用户控件,它公开一个模板来填充用户控件的一部分。我通过创建 ContentTemplate (或 DataTemplate?)类型的 DependencyProperty 使其工作。然后我这样显示

<ContentControl x:Name="PlayerContent" ContentTemplate="{Binding PlayerTemplate, ElementName=W}" />

现在的问题是,当我使用 UserControl 时,我无法在模板中设置元素名称。

<local:MediaPlayerWpf x:Name="PlayerUI" Height="auto" Width="auto">
    <local:MediaPlayerWpf.PlayerTemplate>
        <ControlTemplate>
            <WindowsFormsHost x:Name="Host" Focusable="False" />
        </ControlTemplate>
    </local:MediaPlayerWpf.PlayerTemplate>
</local:MediaPlayerWpf>

这会抛出

无法在元素上设置名称属性值“主机” 'WindowsFormsHost'。 'WindowsFormsHost' 位于 已注册名称的元素“MediaPlayerWpf”的范围 当它在另一个范围内定义时。

因此,我无法访问模板中定义的控件。我还发现无法访问 ContentControl 中显示的子项的根目录。

如何访问模板中定义的“主机”控件?

【问题讨论】:

  • 从哪里访问?请发布显示您要执行的操作的代码。解决方案取决于此。
  • 我多次遇到同样的问题。不记得确切的原因,但我敢肯定,如果您从 Control 而不是 UserControl 继承,您将不会收到此错误。
  • 我想从声明模板内容的窗口访问它。还没有其他代码,UI 无法在 x:Name="Host" 处编译。如果将 UserControl 更改为 Control,则无法定义控件的内容。或者,我可以采用类的类型并创建该类的实例以放置在容器中,而不是使用模板,也许?问题是设计者不允许将属性设置为类型,因此必须在代码隐藏中完成。或者也许只是我传递内容对象的 SetContent() 方法。
  • 之前看过,现在再看一遍:“用户控件不支持复杂的自定义,控件模板,样式难。”

标签: c# wpf


【解决方案1】:

似乎我们不能在 UserControl 中以这种方式使用模板。不知道有没有办法。

我最终采取了不同的方法。我公开了一个属性来设置内容。

public static DependencyProperty HostProperty = DependencyProperty.Register("Host", typeof(PlayerBase), typeof(MediaPlayerWpf), new PropertyMetadata(null, OnHostChanged));
public PlayerBase Host { get => (PlayerBase)base.GetValue(HostProperty); set => base.SetValue(HostProperty, value); }
private static void OnHostChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
    MediaPlayerWpf P = d as MediaPlayerWpf;
    if (e.OldValue != null)
        P.HostGrid.Children.Remove(e.OldValue as PlayerBase);
    if (e.NewValue != null) {
        P.HostGrid.Children.Add(e.NewValue as PlayerBase);
        P.UI.PlayerHost = e.NewValue as PlayerBase;
    }
}

然后在使用类的代码隐藏中,我这样设置

Player.Host = new MpvMediaPlayerHost();

至少它是有效的。

编辑:更好的解决方案是从用户控件切换到自定义控件。我仍然应用了上面的解决方案,切换到自定义控件允许我在派生类的构造函数中设置主机。

【讨论】: