开发者

INotifyPropertyChanged not working for XML Serialization

I have a DataGridView that is bound to a collection. The types in the collection implement INotifyPropertyChanged (textbook implementation from the MSDN page).

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(string name)
    {
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

public string Name
    {
    get { return m_Name; }
    set { m_Name = value; NotifyPropertyChanged("Name"); }
    }

I'm trying to understand when, how and why the PropertyChanged event actually gets fired. If I write code to use the Name property to change the string everything works, PropertyChanged is != NULL, and my DataGridView updates correctly. Like so:

for (int i = 0; i < Server.Customers.Count; i++)
    {
    Server.Customers[i].Name = Server.Customers[i].Name + "!!";
    }

That's just a test, however, the way the collection should really update is via XML deserialization. The implementation for the serializer is very straighforw开发者_如何学Goard, and the code steps through the exactly the same Name property (calling NotifyPropertyChanged) as in the previous example. With one difference: PropertyChanged turns out to be NULL and is never invoked. Result: no update in my data binding.

I don't quite understand what's going on here. I never explicitly subscribe to PropertyChanged in the first place (and neither do any of the code examples I have found), yet it gets invoked correctly in the first example. How do I get this to work for my second example, where I deserialize my XML into the object?


XML serialization can't update an existing object, it always creates a new one when you deserialize. Since it's a new object, there isn't any handler for PropertyChanged yet, so the event isn't fired.

It doesn't make sense to listen to the PropertyChanged event of an object that is being created. What are you trying to do exactly?


I totally agree with Thomas's answer and add a few suggestions:

If you need to use INotifyPropertyChanges you definitely should go some other way to deserialize an object. You can use instance method like InitializeFrom(string xml) or UpdateFrom(string xml). You create an object, subscribe to PropertyChanged event and latter you call UpdateFrom(xml) on existing object. So you will be notified of changes and keep the existing object alive. Here, you can implement the whole thing in the following way:

class MyClass : INotifyPropertyChanges
{
    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    public string Name
    {
        get { return m_Name; }
        set { m_Name = value; NotifyPropertyChanged("Name"); }
    }

    public void UpdateFrom(string xml)
    {
        MyClass deserialized = Deserialize(xml);

        // here you set all properties you have
        Name = deserialized.Name;
        // and all the rest properties...
    }

    private static MyClass Deserialize(string xml)
    {
        XmlSerializer ser = new XmlSerializer(typeof(MyClass));
        using (StringReader reader = new StringReader(xml))
        {
            return (MyClass)ser.Deserialize(reader);
        }
    }
}

Also I would modify NotifyPropertyChanged method so it would not fire when property value hadn't changed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜