Domanda

I have a Node object with a Parent that i have bound in my xaml like so,

<Label>
    <Hyperlink>
        <TextBlock Text="{Binding Path=Node.Parent.Name}"/>
    </Hyperlink>
</Label>

My ViewModel looks something like this

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

}

Why is it that when my if statement is commented out, the label/textblock is blank? Am I doing something wrong? Does my object both exist and not exist until I check if it's null?

Edit:
Forgot to mention, my node class is pretty simple, and does implement INotifyPropertyChanged for the Name property.

2nd Edit: Added my simple Node class.

[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;
    }
}
È stato utile?

Soluzione

From comments:

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.

Altri suggerimenti

I think you are missing to implement INPC on the ViewModel. The binding won't update back to the UI when you did Node = node. Raise a property changed event on the Node setter.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top