Schrodinger's Object: WPF属性不能绑定/更新,除非我在代码端检查它的值
本文关键字:非我 代码 检查 更新 Object 绑定 不能 属性 WPF Schrodinger | 更新日期: 2023-09-27 17:51:13
我在xaml中绑定了一个带有Parent的Node对象,如下所示
<Label>
<Hyperlink>
<TextBlock Text="{Binding Path=Node.Parent.Name}"/>
</Hyperlink>
</Label>
我的ViewModel看起来像这样
public class NodeViewModel
{
public Node Node { get; set; }
public NodeViewModel(Node model)
{
Node = model;
if(model.Parent != null) { } // Check if it's null, then do nothing.
// When the above line is commented out, my label displays nothing.
}
}
为什么当我的if语句被注释掉时,标签/文本块是空白的?我做错了什么吗?我的对象是否既存在又不存在直到我检查它是否为空?
编辑:
忘了提一下,我的节点类非常简单,并且为Name属性实现了INotifyPropertyChanged
。
第二次编辑:添加了我的简单Node类。
[ImplementPropertyChanged] // From Fody.PropertyChanged
public class Node
{
public int? ParentID { get; set; }
public Node Parent { get; set; }
public string Name { get; set; }
public Node Node(Node p = null)
{
Parent = p;
}
}
From comments:
它实际上是。它由实体框架代理。这是问题所在吗?如果是这样,有没有不那么俗气的办法来解决这个问题?
如果 问题真的出在代理上,那么,好吧,不是。使用代理/包装器、WPF和更改通知,真的会很困难。
WPF的绑定引擎不能与代理一起工作。在所有。也许吧,除非它们写得很好而且很复杂。所以,通常不会。这源于INPC接口的工作方式:void PropertyChanged(object sender, .... args)
WPF跟踪sender
和Binding.Source
。如果绑定的源是一个名为"Z"的对象,它是对象"a"的代理,那么由代理"Z"转发到WPF引擎的任何来自"a"的通知都是…丢弃,因为对于WPF来说,"Z"是源,它与发布的发送方"A"不匹配。
我与这个问题斗争了很长一段时间,我发现的只有解决方案是让代理翻译 p - changed事件,以便sender=A
取代Z
。如果没有正确编写,这可能会导致一些严重的内存泄漏。这是因为很难将一个委托"映射"到一个新的委托,并为它们提供适当的处理和绑定。通常情况下,这只有在使用ie构建自己的代理时才有可能实现。城堡或类似的图书馆。我还没有找到任何支持sender
替换的动态代理库。
如果你知道任何-请让我知道!
无论如何,要注意术语。我的意思是,代理。一个对象"Z",它对另一个不同的原始对象"A"进行包装、裁剪或扩展操作。您的情况可能与不同。如果你所谓的"代理"是你的类型的一个动态子类,如果它覆盖任何虚拟方法/属性/事件,你在你的原始类,那么它是不是代理我的意思。在这种情况下,"代理"和原始对象是同一个对象,只是您将其视为类a,而实际类是Z:A
,对于WPF, Source
匹配sender
。如果我没记错的话,这就是EF的工作方式。
因此,我要检查的第一件事是检查谁是真正的罪魁祸首。也许福迪不是EF?尝试删除那个神奇的ImplementPropertyChanged
,尝试在所有类中手动实现INPC 。我指的是全部。在Node
和NodeViewModel
。如果你很懒,你可以用propdp
代替DependencyProperty
。如果它工作-然后开始删除手动INPC并替换为ie。那是福迪的。当事情开始出现问题时,收集所有结果并重新分析。
另外,检查Fody做了什么-也许它在某些方面提供了透明的代理/包装器?
编辑:考虑到你的代码开始工作时,你"触摸"Fody' ed对象,我开始责怪Fody。也许是因为NodeViewModel.Node
属性目前没有被跟踪,但是Fody?你也试过用ImplementPropertyChanged
标记它吗?这是一个纯粹的猜测,这意味着这个库有一些严重的问题,但它是快速的,值得一试。
我认为你错过了在ViewModel
上实现INPC
。当您执行Node = node
时,绑定不会更新回UI
。在Node
setter上引发一个property changed
事件