wpf - 当我有可交换的子部件时,为什么需要使用外观控件而不是 UserControl

标签 wpf xaml

我有一个 WPF 应用程序,其中包含一些自定义控件(在同一项目内定义),这些控件具有可交换的子部分。作为一个基本示例,假设我有一些 Xaml,例如:

<Border Background="White" CornerRadius="9">
    <ContentPresenter/>
</Border>

它用于我的从 ContentControl 派生的类,我们称之为 MrWhiteControl

如果我将 MrWhiteControl 设为 xaml 和代码隐藏文件对(因此它在 ctor 中有一个 InitializeComponent() 调用),那么无论我在 Content 属性有很多问题,例如DataContext 将无法正确继承,并且在绑定(bind)中使用 ElementName 将不起作用。

但是,如果我使用 lookless control - 因此,MrWhiteControl.cs 文件的样式在 Themes/Generic.xaml 中定义(我不关心此应用程序中的主题支持) - 然后一切正常。

我想知道的是为什么会这样。幕后发生了什么,意味着外观控件工作正常,但带有代码隐藏的 xaml 无法正常工作?

我创建了一个example project you can clone from GitHub 。如果运行它,您将看到 ElementName 绑定(bind)在具有代码隐藏的控件(列表中的第二个)中不起作用,但在无外观的控件(底部列表)。

托管内容演示者的外观控件和用户控件之间有什么区别?

最佳答案

编辑:添加了一个解决方案,使绑定(bind)能够在底部使用此方法。


问得好。

AFAICT 这只是因为 DP 的设置方式以及何时根据 NameScope 解析绑定(bind)。

MainWindow.xaml 中,您通过代码隐藏为控件分配 DP MyContent 属性,该属性将整个 TextBox 代码作为DP 值。因此此时绑定(bind)尚未解决。

当应用 Binding 时,在 UserControl 的范围内,找不到 ElementName,我们可以验证是否将另一个 TextBox 添加到该 UserControl 中,例如

<StackPanel>
  <TextBox Name="textBox" Text="Sampleeeeeeee" />
  <ContentPresenter Content="{Binding MyContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type LookslessVsUserControl:MrWhiteWithCodeBehind}}}" />
</StackPanel>

现在我们得到了

enter image description here

当绑定(bind)被解析时,新的 TextBox 是在范围内的,而不是来自 MainWindow.xaml

对于 Style,应用 Style 的范围保持相同,因此它会找到 MainWindow.xaml 的文本框。因此,我们只有一层嵌套,这也可以从 Snoop 中看到

enter image description here

解决方案:

如果您更喜欢通过该方法设置 DP 与控件,您仍然可以使 Binding 正常工作:

在您的 MainWindow.xaml.cs 中,您需要相应地设置 UserControl 的名称范围,以便它不会使用自己的 WPF Xaml NameScope

在 MainWindow.xaml.cs 的 ctor() 中:

Loaded += (sender, args) => NameScope.SetNameScope(problemControl, NameScope.GetNameScope(this));

在 xaml 中我将其命名为 problemControl 例如:

<LookslessVsUserControl:MrWhiteWithCodeBehind x:Name="problemControl">
  <LookslessVsUserControl:MrWhiteWithCodeBehind.MyContent>
    <TextBlock Text="{Binding ElementName=textBox, Path=Text}" />
  </LookslessVsUserControl:MrWhiteWithCodeBehind.MyContent>
</LookslessVsUserControl:MrWhiteWithCodeBehind>

这样,当 UserControl 加载并尝试解析 Binding 时,它应该可以找到 TextBox 并为您提供所需的输出。

关于wpf - 当我有可交换的子部件时,为什么需要使用外观控件而不是 UserControl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22712206/

相关文章:

c# - 隐藏ListView中的按钮

c# - 将 MahApps.Metro 主题和重音应用于其他控件或矩形

c# - UserControl 元素由于其保护级别而无法访问

c# - SaveFileDialog 上的 DialogResult.OK 不起作用

c# - 如何获取包含 ItemsControl 内容的 Panel 实例?

c# - WPF MVVM : Access a listview object from View Model

.net - 在WPF DataGrid中双击显示RowDetails

c# - 多个 ItemsSource 集合绑定(bind)

c# - XAML 序列化 - 需要指定属性

c# - 是否可以为 XAML 绑定(bind)到 View 模型启用智能感知?