Content.Binding.ElementName vs DataContext.Binding.ElementName,任何人都可以解释这些微妙的差异吗?

时间:2017-12-20 17:37:10

标签: c# wpf xaml

我在WPF中遇到了以下奇怪的行为:

假设我有一个在SomeWindow中实现的Window:

<Window x:Name="MainWindow" x:Class="SomeWindow">

</Window>

在这个类中,我公开了两个公共属性:一个是SomeModel类型,另一个是ObservableCollection类型&lt; SomeModel&gt;。 SomeModel实现了INotifyPropertyChanged并公开了一个通知属性SomeProperty。

public partial class SomeWindow : Window
{
   public ObservableCollection<SomeModel> ListOfSomeModel { get; set; }
   public SomeModel InstanceOfSomeModel { get; set; }
}

两者都在其他地方初始化,但是及时。

现在我可以通过几种不同的方式将这些属性绑定到WPF控件:

方法1

我将Window的DataContext设置为自身。当孩子们没有设置时,孩子们会使用这个值。

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

接下来,我按照以下方式在XAML中进行绑定:

<Label x:Name="Label1" Content="{Binding Path=ListOfSomeModel[0].SomeProperty}" />
<Label x:Name="Label2" Content="{Binding Path=InstanceOfSomeModel.SomeProperty}" />

这很有效。 (如:两个标签都绑定到引用的对象,并在数据突变时更新。)

方法2

SomeWindow中没有默认的DataContext,但是在XAML中的元素本身上设置了DataContext。

<Label x:Name="Label1" DataContex="{Binding ElementName=SomeWindow}" Content="{Binding Path=ListOfSomeModel[0].SomeProperty}" />
<Label x:Name="Label2" DataContex="{Binding ElementName=SomeWindow}" Content="{Binding Path=InstanceOfSomeModel.SomeProperty}" />

这也有效。到目前为止,太棒了!

方法3

现在最后,我根本没有设置DataContext,而是直接在Content上设置Binding.ElementName。

<Label x:Name="Label1" Content="{Binding ElementName=SomeWindow, Path=ListOfSomeModel[0].SomeProperty}" />

不起作用。好吧,也许我没有正确理解设置DataContext与直接告诉Binding在哪里看的细微差别。也许这样你只能访问基类的内置属性。或许.......

......但等待

另一个仍然有效:

<Label x:Name="Label2" Content="{Binding ElementName=SomeWindow, Path=InstanceOfSomeModel.SomeProperty}" />

所以任何人都可以解释这两种方法的技术工作以及为什么在方法3中,ObservableCollection的元素不再可访问(或至少可绑定)?或者我忽略了一些微不足道的事情?

免责声明

  • 我知道通过索引访问无序集合是不安全的。
  • 我知道在XAML中添加对集合成员的引用是荒谬的,因为你永远无法确定它是否存在而且它仍然很疯狂,我应该使用ViewModel等等。

就像这样来证明观察到的行为。

1 个答案:

答案 0 :(得分:-1)

这是在上述评论的帮助下解决的。

主要罪魁祸首(来自我原来的问题):

  

两者都在其他地方初始化,但是及时。

这是错误的。它们没有及时初始化,但是在InitializeComponent()之后。我没有注意到,因为方法1和方法2确实有效。

所以&#39;微妙的差异&#39;我一直在寻找:

在方法1和方法2的情况下,设置了永久的DataContext,因此即使由于集合尚未初始化而导致值的初始绑定失败,由引发的PropertyChanged事件DO触发的后续更新也会成功。 在方法3的情况下,未设置永久DataContext,并且在初始失败绑定之后,控件将完全未绑定,并且不会响应其他PropertyChanged事件。

感谢您的帮助!