在UserControl中设置DataContext会影响父级绑定

16

我有一个基本的 UserControl,它将其 DataContext 设置为自己以便于绑定:

<UserControl x:Class="MyControlLib.ChildControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

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

</UserControl>

这是在一个父XAML文件中使用的示例:

<UserControl x:Class="MyControlLib.ParentControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:ctrl="clr-namespace:MyControlLib">

             <ctrl:ChildControl x:Name="ChildName" 
                                PropertyOnChild="{Binding PropertyInParentContext}"/>             
</UserControl>
由于某些原因,这会引发一个绑定错误,似乎表明父控件的DataContext受到子控件设置自己的DataContext的影响。

System.Windows.Data Error: 40 : BindingExpression path error: 'PropertyInParentContext' property not found on 'object' ''ChildControl' (Name='ChildName')'. BindingExpression:Path=PropertyInParentContext; DataItem='ChildControl' (Name='ChildName'); target element is 'ChildControl' (Name='ChildName'); target property is 'PropertyOnChild' (type 'whatever')

为什么会在子控件中寻找“PropertyInParentContext”,而不是在父控件的DataContext中查找?
如果我移除...
DataContext="{Binding RelativeSource={RelativeSource Self}}

如果从子控件开始操作,那么事情就会按照我的预期进行。

我是否漏掉了什么显而易见的东西?

2个回答

12

你控件的声明和实例化基本上是操作同一个对象,声明中设置的所有属性也会在每个实例中设置。因此,如果属性是“可见”的话:

<UserControl x:Class="MyControlLib.ParentControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:ctrl="clr-namespace:MyControlLib">
    <ctrl:ChildControl x:Name="ChildName" 
                       DataContext="{Binding RelativeSource={RelativeSource Self}}"
                       PropertyOnChild="{Binding PropertyInParentContext}"/>
</UserControl>
这就是为什么您不应该设置UserControlsDataContext,它会覆盖继承的DataContext(甚至掩盖了存在不同上下文的事实)。如果您想要在声明中绑定UserControl的属性,则需要给控件命名并使用ElementNameRelativeSource绑定。

谢谢,我误解了绑定的范围,你的帖子解释得很清楚。我一直认为UserControl的XAML是自包含的,就像模板一样,但我想它只是文档的一部分。 - GazTheDestroyer

5

Self意味着UserControl,因此当您将DataContext设置为Self时,您正在将DataContext设置为UserControl对象。

绑定控件的DataContext的正确语法应该是{Binding RelativeSource = {RelativeSource Self},Path = DataContext},不过由于DataContext被父控件继承,所以在任何情况下都没有必要进行此绑定。

另外,如果您将DataContext绑定到Self.DataContext,则本质上会创建一个绑定到自身的循环。


是的,那正是我想做的——将DataContext设置为UserControl。我没有意识到这会影响“父”控件中的绑定语句。 - GazTheDestroyer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接