wpf UserControl 的 DataContext

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5077377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:36:31  来源:igfitidea点击:

UserControl's DataContext

wpfxamldatacontext

提问by svick

I'm creating a UserControlI want to use something like this:

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

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

So far, I've implemented similar controls like this:

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

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

where Colorand Textare dependency properties of the control defined in code. This works, but specifying ElementNameevery time seems unnecessary.

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

Another option that works is using

另一个有效的选择是使用

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

and not specifying ElementNames, but that doesn't seem like a clean solution to me either.

并没有指定ElementNames,但这对我来说似乎也不是一个干净的解决方案。

I have two questions:

我有两个问题:

  1. Why doesn't <UserControl DataContext="{RelativeSource Self}">work?
  2. What is the best way to do something like this?
  1. 为什么不起作用<UserControl DataContext="{RelativeSource Self}">
  2. 做这样的事情的最好方法是什么?

回答by decyclone

For first one, try :

对于第一个,请尝试:

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

And for second question, I think using ElementNameor AncestorBindingis best way to bind to UserControl's properties.

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

回答by pdross

Why can't you use <UserControl DataContext="{RelativeSource Self}">?

为什么不能用<UserControl DataContext="{RelativeSource Self}">

This is how you would use the control

这是您使用控件的方式

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

Now because we've hardcoded our data-context in the control it will instead attempt to lookup ColorToUse property on the ColorWithText objectnot your ViewModel, which will obviously fail.

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

This is why you can't set the DataContext on the user control. Thanks to Brandurfor making me understand that.

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

What is the best way to do something like this?

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

Instead you should set the DataContext in the first child UI element in your control.

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

In your case you want

在你的情况下你想要

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

Now you have a DataContext which refers to your control so you can access any properties of that control using relative bindings.

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

回答by jdawiz

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.

我知道这已经得到了回答,但没有一个解释给出了对 DataContext 及其工作原理的理解。这个链接在这方面做得很好。

EVERYTHING YOU WANTED TO KNOW ABOUT DATABINDING IN WPF, SILVERLIGHT AND WP7 (PART TWO)

您想知道的关于 WPF、SILVERLIGHT 和 WP7 中的数据绑定的一切(第二部分)

In answer to your question #1

回答你的问题#1

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

为什么不起作用<UserControl DataContext="{RelativeSource Self}">

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 不应在 UserControl 元素级别设置为 Self。这是因为它破坏了 DataContext 的继承。如果确实将其设置为 self 并将此控件放置在 Window 或其他控件上,则它不会继承 Windows DataContext。

DataContext is inherited to all lower Elements of the XAML and to all the XAML of UserControls unless it is overwritten somewhere. By setting the UserControl DataContext 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.

DataContext 继承到 XAML 的所有较低元素和 UserControls 的所有 XAML,除非它在某处被覆盖。通过将 UserControl DataContext 设置为自身,这会覆盖 DataContext 并破坏继承。相反,将它嵌套在 XAML 深处的一个 Element 中,在您的情况下是 StackPanel。将 DataContext 绑定放在这里并将其绑定到 UserControl。这保留了继承。

See also this link below for a detailed explanation of this.

另请参阅下面的此链接以获取对此的详细说明。

A SIMPLE PATTERN FOR CREATING RE-USEABLE USERCONTROLS IN WPF / SILVERLIGHT

在 WPF / SILVERLIGHT 中创建可重复使用的用户控件的简单模式

In answer to your question #2
What is the best way to do something like this?

回答您的问题#2
做这样的事情的最佳方法是什么?

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>

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

请注意,一旦执行此操作,您将不需要每个绑定上的 ElementName。

回答by Prince Ashitaka

You should be using

你应该使用

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

for Databinding Related doubts always refer this sheet.
http://www.nbdtech.com/Blog/archive/2009/02/02/wpf-xaml-data-binding-cheat-sheet.aspx

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

回答by biju

You can set the datacontext to self at the constructor itself.

您可以在构造函数本身将数据上下文设置为 self 。

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

Now you can simply say

现在你可以简单地说

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