UserControl的DataContext

svi*_*ick 41 wpf datacontext xaml

我正在创建一个UserControl我想要使​​用这样的东西:

<controls:ColorWithText Color="Red" Text="Red color" />
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经实现了类似的控件:

<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
    <StackPanel Orientation="Horizontal" >
        <Border Width="15" Height="15" Background="{Binding Color, ElementName=ThisControl}" />
        <TextBlock Text="{Binding Text, ElementName=ThisControl}" />
    </StackPanel>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

where ColorText是代码中定义的控件的依赖项属性.这有效,但ElementName每次指定似乎都没有必要.

另一个有用的选择是使用

<UserControl x:Class=… DataContext="{Binding ElementName=ThisControl}" Name="ThisControl">
Run Code Online (Sandbox Code Playgroud)

并没有指定ElementNames,但这对我来说似乎也不是一个干净的解决方案.

我有两个问题:

  1. 为什么不起作用<UserControl DataContext="{RelativeSource Self}">
  2. 做这样的事情的最佳方法是什么?

dec*_*one 57

首先,尝试:

<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
Run Code Online (Sandbox Code Playgroud)

对于第二个问题,我认为使用ElementName或是AncestorBinding绑定到UserControl属性的最佳方式.

  • 我知道这是一个旧帖子,但对于其他任何人来到她......你没有为个人控制设置VM.您可以在控件上设置属性,这些属性应足以使其"正常工作".如果控件依赖于某个VM或者紧密耦合/取决于被置于特定的上下文中工作那么它就不是"控制".你违反了关注点分离原则. (5认同)
  • 据我所知,这打破了任何带有“DependencyProperty”的“UserControl”。请参阅 https://nikolalukovic.com/programming/WPF-Custom-UserControl-datacontext-binding-gotcha.html 和/或@jdawiz 的回答。 (4认同)

pdr*_*oss 20

你为什么不能用<UserControl DataContext="{RelativeSource Self}">

这是你如何使用控件

<Grid DataContext="{StaticResource ViewModel}">
    <!-- Here we'd expect this control to be bound to -->
    <!-- ColorToUse on our ViewModel resource          -->
    <controls:ColorWithText Color="{Binding ColorToUse}" />
</Grid>
Run Code Online (Sandbox Code Playgroud)

现在因为我们在控件中硬编码了我们的数据上下文,它将尝试在ColorWithText对象上查找ColorToUse属性而不是ViewModel,这显然会失败.

这就是您无法在用户控件上设置DataContext的原因.感谢Brandur让我明白这一点.

做这样的事情的最佳方法是什么?

相反,您应该在控件中的第一个子UI元素中设置DataContext.

在你的情况下你想要的

<StackPanel 
  DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
  Orientation="Horizontal" >
Run Code Online (Sandbox Code Playgroud)

现在您有一个引用控件的DataContext,因此您可以使用相对绑定访问该控件的任何属性.


jda*_*wiz 14

我知道这已经得到了回答,但没有一个解释能够理解DataContext及其工作原理.这个链接做得很好.

您希望了解WPF,SILVERLIGHT和WP7中的数据量的一切(第二部分)

回答你的问题#1

为什么不起作用<UserControl DataContext="{RelativeSource Self}">

这是上述链接的摘要.不应在UserControl元素级别将DataContext设置为Self.这是因为它破坏了DataContext的继承.如果您将其设置为self并将此控件放在Window或其他控件上,则它将不会继承Windows DataContext.

DataContext继承到XAML的所有下层元素和UserControls的所有XAML,除非它被覆盖在某处.通过将UserControl DataContext设置为自身,这将覆盖DataContext并中断继承.相反,将它放在XAML中的一个元素深处,在您的情况下,StackPanel.将DataContext绑定放在此处并将其绑定到UserControl.这保留了继承.

有关详细说明,请参见下面的链接.

在WPF/SILVERLIGHT中创建可重用的USERCONTROL的简单模式

回答你的问题#2
做这样的事情的最佳方法是什么?

请参阅下面的代码示例

<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
    <StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=ThisControl}">
    <Border Width="15" Height="15" Background="{Binding Color" />
    <TextBlock Text="{Binding Text}" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

请注意,一旦执行此操作,您将不需要每个绑定上的ElementName.


Pri*_*aka 13

你应该使用

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=Color}
Run Code Online (Sandbox Code Playgroud)

对于数据绑定相关疑问总是参考此表.
http://www.nbdtech.com/Blog/archive/2009/02/02/wpf-xaml-data-binding-cheat-sheet.aspx


bij*_*iju 10

您可以在构造函数本身将datacontext设置为self.

public ColorWithText()
{
 InitializeComponent();
 DataContext = this;
}
Run Code Online (Sandbox Code Playgroud)

现在你可以简单地说

<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
    <StackPanel Orientation="Horizontal" >
        <Border Width="15" Height="15" Background="{Binding Color}" />
        <TextBlock Text="{Binding Text}" />
    </StackPanel>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

  • 甚至在加载事件中 this.Loaded += (sender, e) =&gt; { this.DataContext = this; }; (2认同)