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。