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

时间:2011-09-27 15:50:10

标签: wpf xaml data-binding user-controls datacontext

我有一个基本UserControlDataContext设置为自身以便于绑定:

<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错误:40:BindingExpression路径错误:'object'''ChildControl'(Name ='ChildName')'上找不到'PropertyInParentContext'属性。 BindingExpression:路径= PropertyInParentContext; DataItem ='ChildControl'(Name ='ChildName'); target元素是'ChildControl'(Name ='ChildName'); target属性是'PropertyOnChild'(输入'whatever')

为什么“PropertyInParentContext”正在子控件中而不是在父级DataContext中查找?

如果我删除

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

来自儿童控制,然后事情按照我的预期运作。

我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:11)

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

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

这就是为什么你没有设置DataContext的{​​{1}},它会覆盖继承的UserControls(甚至混淆了存在不同上下文的事实)。如果要在其声明中绑定DataContext的属性,请为控件命名并使用UserControlElementName - 绑定。

答案 1 :(得分:5)

Self表示UserControl,因此当您将DataContext设置为Self时,您将DataContext设置为UserControl对象

绑定到Control的DataContext的正确语法是{Binding RelativeSource={RelativeSource Self}, Path=DataContext},但是由于DataContext是Parent继承的,所以在任何情况下这种绑定都是完全不必要的。

此外,如果您将DataContext绑定到Self.DataContext,您实际上将创建一个循环,其中值绑定到自身。