UserControl的DataContext

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

 <controls:ColorWithText Color="Red" Text="Red color" /> 

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

 <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> 

其中ColorText是在代码中定义的控件的依赖项属性。 这工作,但每次指定ElementName似乎没有必要。

另一个可行的select是使用

 <UserControl x:Class=… DataContext="{Binding ElementName=ThisControl}" Name="ThisControl"> 

而不是指定ElementName ,但是这对我来说也不是一个干净的解决scheme。

我有两个问题:

  1. 为什么不<UserControl DataContext="{RelativeSource Self}">工作?
  2. 什么是这样做的最好方法?

对于第一个,请尝试:

 <UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}"> 

而对于第二个问题,我认为使用ElementNameAncestorBinding是绑定到UserControl的属性的最佳方法。

你应该使用

 {Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=Color} 

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

为什么不能使用<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> 

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

这就是为什么你不能在用户控件上设置DataContext的原因。 感谢Brandur让我明白这一点。

什么是这样做的最好方法?

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

在你的情况下,你想要的

 <StackPanel DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Orientation="Horizontal" > 

现在你有一个引用你的控件的DataContext,所以你可以使用相对绑定访问该控件的任何属性。

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

 public ColorWithText() { InitializeComponent(); DataContext = this; } 

现在你可以简单地说

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

我知道这已经得到了答案,但是没有一个解释给出了对DataContext的理解以及它是如何工作的。 这个链接为此做了很好的工作。

所有你想知道WPF,SILVERLIGHT和WP7中的数据库(第二部分)

回答你的问题#1

为什么不<UserControl DataContext="{RelativeSource Self}">工作?

这是以上链接的摘要。 在UserControl元素级别不应将DataContext设置为Self。 这是因为它打破了DataContext的inheritance。 如果您将其设置为self,并将此控件放在Window或另一个控件上,则它将不会inheritanceWindows DataContext。

DataContext被inheritance到XAML的所有下层元素,并且被所有的UserControls的XAML所覆盖,除非被覆盖在某个地方。 通过将UserControl DataContext设置为自身,将覆盖DataContext并中断inheritance。 相反,将它embedded到XAML的一个元素深处,在您的情况下,StackPanel。 把DataContext绑定在这里,并将其绑定到UserControl。 这保留了inheritance。

有关详细说明,请参阅下面的链接。

用于在WPF / SILVERLIGHT中创build可重用的用户控件的简单模式

回答你的问题#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> 

请注意,一旦你这样做,你将不需要每个绑定的ElementName。