4

我有一个带有 Parent 的 Node 对象,我像这样绑定在我的 xaml 中,

<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 语句被注释掉时,标签/文本块是空白的?难道我做错了什么?在我检查它是否为空之前,我的对象是否既存在又不存在?

编辑:
忘了提一下,我的节点类非常简单,并且确实INotifyPropertyChanged为 Name 属性实现了。

第二次编辑:添加了我的简单节点类。

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

2 回答 2

3

来自评论:

It is actually. It is proxied by Entity Framework. Could that be the issue? If so, is there a less hackish way to fix this?

If the problem really lies in the proxy, then, well, no. You'll get a hard time with proxies/wrappers and WPF and change-notifications, really.

WPF's Binding engine does not work with proxies. At all. Well, maybe unless they are really well written and complex. So, usually, never. This comes form the fact how INPC interface works:

void PropertyChanged(object sender, .... args)

WPF tracks the sender and Binding.Source. If a Source of a Binding is an object called "Z", that is a Proxy to an object "A", then any notifications originating from "A" that are forwarded by proxy "Z" to the WPF's engine are .. discarded because for WPF the "Z" is the Source and it does not match the advertised sender "A".

I battled with this issue for quite a long time, and the only solution I found is to have the Proxy translate the P-Changed event so that the sender=A is subsituted for Z. This can have some nasty memory leaks when not written properly. It's because it's hard to "map" a delegate to a new delegate and provide proper disposal and GCing of both of them. And usually even this is only possible if you build your own proxies with ie. Castle or similar library. I have not found any dynamic-proxy library that supports sender-replacement out of the box.

If you know any - pleease let me know!

Anyways, be careful with the terminology. I mean, proxies. An object "Z" that wraps and trims or extends operations on another different original object "A". Your case may be different. If your so-called "proxy" is a dynamic subclass of your type and if it overrides any virtual methods/properties/events you have in your original class, then it is not the Proxy I meant. In this case, the 'proxy' and the original object is the same object, it's just that you see it as a class A and the actual class is Z:A, and for WPF the Source matches the sender. If I remember correctly, this is how EF often works.

Therefore, the first thing I'd check is to inspect who is really the culprit. Maybe Fody not EF? Try to remove that magic ImplementPropertyChanged, try to implement INPC manually in ALL classes. And I mean ALL. Both in Node and in NodeViewModel. If you are lazy, you can propdp and use DependencyProperty instead. If it works - then start removing the manual INPC and replacing it with ie. that from Fody's. When things start to break, gather all results and reanalyze.

Also, check what Fody does - maybe it provides a transparent proxy/wrapper in some point?

EDIT: Considering that your code starts working when you 'touch' the Fody'ied object, I'd start blaming Fody. Maybe it is because the NodeViewModel.Node property is currently not tracked bu Fody? Have you tried marking it with ImplementPropertyChanged too? It is a pure guess and it'd mean that this library has some serious problems, but it's quick and worth trying.

于 2014-03-21T19:53:51.063 回答
0

我认为您缺少INPCViewModel. 绑定不会更新回UI你做的时候Node = node。在setter上引发property changed事件。Node

于 2014-03-21T19:37:03.420 回答