XAML 用户控件的数据上下文

rks48beu  于 2022-12-07  发布在  其他
关注(0)|答案(6)|浏览(142)

我创建了一个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
另一个可行的方法是使用

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

并且不指定ElementName s,但对我来说,这似乎也不是一个干净的解决方案。
我有两个问题:
1.为什么<UserControl DataContext="{RelativeSource Self}">不起作用?
1.做这种事情的最好方法是什么?

1bqhqjot

1bqhqjot1#

对于第一个,请尝试:

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

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

balp4ylt

balp4ylt2#

为什么不能使用<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,因此可以使用相对绑定访问该控件的任何属性。

2lpgd968

2lpgd9683#

I know this has been answered but none of the explanations give an Understanding of DataContext and how it works. This link does a great job for that.
EVERYTHING YOU WANTED TO KNOW ABOUT DATABINDING IN WPF, SILVERLIGHT AND WP7 (PART TWO)
In answer to your question #1

Why doesn't <UserControl DataContext="{RelativeSource Self}"> work?

This is a summary of the above link. DataContext should not be set to Self at UserControl Element level. This is because it breaks the Inheritance of the DataContext . If you do set it to self and you place this control on a Window or another control, it will not inherit the Windows DataContext .
DataContext is inherited to all lower Elements of the XAML and to all the XAML of UserControl s unless it is overwritten somewhere. By setting the UserControlDataContext to itself, this overwrites the DataContext and breaks Inheritance. Instead, nest it one Element deep in the XAML, in your case, the StackPanel . Put the DataContext binding here and bind it to the UserControl . This preserves the Inheritance.
See also this link below for a detailed explanation of this.
A SIMPLE PATTERN FOR CREATING RE-USEABLE USERCONTROLS IN WPF / SILVERLIGHT
In answer to your question #2 What is the best way to do something like this?
See code example below.

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

Note that once you do this, you will not need the ElementName on each binding.

w8biq8rn

w8biq8rn4#

你应该用

{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

vwkv1x7d

vwkv1x7d5#

可以在构造函数本身将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>
vc9ivgsu

vc9ivgsu6#

对于那些绝望的灵魂,他们试图让pdross的答案起作用,但却不能:
它缺少了一个重要的细节-Path=DataContext。当您将其添加到下面的代码段时,它开始工作,结果如下:

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

相关问题