我正在创建一个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
似乎没必要。
另一个可行的选择是使用
<UserControl x:Class=… DataContext="{Binding ElementName=ThisControl}" Name="ThisControl">
并没有指定ElementName
,但这对我来说似乎也不是一个干净的解决方案。
我有两个问题:
<UserControl DataContext="{RelativeSource Self}">
无效?答案 0 :(得分:57)
首先,请尝试:
<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
对于第二个问题,我认为使用ElementName
或AncestorBinding
是绑定UserControl
属性的最佳方式。
答案 1 :(得分:18)
<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对象上查找ColorToUse属性,而不是ViewModel,这显然会失败。
这就是您无法在用户控件上设置DataContext的原因。感谢Brandur让我了解这一点。
相反,您应该在控件中的第一个子UI元素中设置DataContext。
在你的情况下你想要
<StackPanel
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
Orientation="Horizontal" >
现在你有一个DataContext引用你的控件,所以你可以使用相对绑定访问该控件的任何属性。
答案 2 :(得分:13)
你应该使用
{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
答案 3 :(得分:10)
您可以在构造函数本身将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>
答案 4 :(得分:10)
我知道这已得到解答,但没有一个解释能够理解DataContext及其工作原理。这个链接做得很好。
EVERYTHING YOU WANTED TO KNOW ABOUT DATABINDING IN WPF, SILVERLIGHT AND WP7 (PART TWO)
回答你的问题#1
为什么<UserControl DataContext="{RelativeSource Self}">
无效?
这是上述链接的摘要。 不应在UserControl元素级别将DataContext设置为Self。这是因为它破坏了DataContext的继承。如果您将其设置为self并将此控件放在Window或其他控件上,则它将不会继承Windows DataContext。
DataContext继承到XAML的所有下层元素和UserControls的所有XAML,除非它被覆盖在某处。通过将UserControl DataContext设置为自身,这将覆盖DataContext并中断继承。相反,将它放在XAML中的一个元素深处,在您的情况下,StackPanel。将DataContext绑定放在此处并将其绑定到UserControl。这保留了继承。
有关详细说明,请参阅下面的链接。
A SIMPLE PATTERN FOR CREATING RE-USEABLE USERCONTROLS IN WPF / SILVERLIGHT
回答你的问题#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。