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

Schrodinger's Object: WPF属性不能绑定/更新,除非我在代码端检查它的值

From comments:

它实际上是。它由实体框架代理。这是问题所在吗?如果是这样,有没有不那么俗气的办法来解决这个问题?

如果 问题真的出在代理上,那么,好吧,不是。使用代理/包装器、WPF和更改通知,真的会很困难。

WPF的绑定引擎不能与代理一起工作。在所有。也许吧,除非它们写得很好而且很复杂。所以,通常不会。这源于INPC接口的工作方式:
void PropertyChanged(object sender, .... args)

WPF跟踪senderBinding.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 。我指的是全部。在NodeNodeViewModel。如果你很懒,你可以用propdp代替DependencyProperty。如果它工作-然后开始删除手动INPC并替换为ie。那是福迪的。当事情开始出现问题时,收集所有结果并重新分析。

另外,检查Fody做了什么-也许它在某些方面提供了透明的代理/包装器?

编辑:考虑到你的代码开始工作时,你"触摸"Fody' ed对象,我开始责怪Fody。也许是因为NodeViewModel.Node属性目前没有被跟踪,但是Fody?你也试过用ImplementPropertyChanged标记它吗?这是一个纯粹的猜测,这意味着这个库有一些严重的问题,但它是快速的,值得一试。

我认为你错过了在ViewModel上实现INPC。当您执行Node = node时,绑定不会更新回UI。在Node setter上引发一个property changed事件