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>
其中Color
和Text
是在代码中定义的控件的依赖项属性。 这工作,但每次指定ElementName
似乎没有必要。
另一个可行的select是使用
<UserControl x:Class=… DataContext="{Binding ElementName=ThisControl}" Name="ThisControl">
而不是指定ElementName
,但是这对我来说也不是一个干净的解决scheme。
我有两个问题:
- 为什么不
<UserControl DataContext="{RelativeSource Self}">
工作? - 什么是这样做的最好方法?
对于第一个,请尝试:
<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
而对于第二个问题,我认为使用ElementName
或AncestorBinding
是绑定到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。