我在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的元素不再可访问(或至少可绑定)?或者我忽略了一些微不足道的事情?
免责声明
就像这样来证明观察到的行为。
答案 0 :(得分:-1)
这是在上述评论的帮助下解决的。
主要罪魁祸首(来自我原来的问题):
两者都在其他地方初始化,但是及时。
这是错误的。它们没有及时初始化,但是在InitializeComponent()之后。我没有注意到,因为方法1和方法2确实有效。
所以&#39;微妙的差异&#39;我一直在寻找:
在方法1和方法2的情况下,设置了永久的DataContext,因此即使由于集合尚未初始化而导致值的初始绑定失败,由引发的PropertyChanged事件DO触发的后续更新也会成功。 在方法3的情况下,未设置永久DataContext,并且在初始失败绑定之后,控件将完全未绑定,并且不会响应其他PropertyChanged事件。
感谢您的帮助!