【问题标题】:INotifyPropertyChanged not working for XML SerializationINotifyPropertyChanged 不适用于 XML 序列化
【发布时间】:2011-04-17 22:26:15
【问题描述】:

我有一个绑定到集合的 DataGridView。集合中的类型实现 INotifyPropertyChanged(来自 MSDN 页面的教科书实现)。

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

我试图了解 PropertyChanged 事件实际被触发的时间、方式和原因。如果我编写代码以使用 Name 属性更改字符串,一切正常,PropertyChanged 为 != NULL,并且我的 DataGridView 更新正确。像这样:

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

这只是一个测试,然而,集合应该真正更新的方式是通过 XML 反序列化。序列化程序的实现非常简单,代码逐步执行与前面示例完全相同的 Name 属性(调用 NotifyPropertyChanged)。有一个区别:PropertyChanged 结果是 NULL 并且永远不会被调用。结果:我的数据绑定没有更新。

我不太明白这里发生了什么。我从来没有明确订阅 PropertyChanged(我发现的任何代码示例也没有),但它在第一个示例中被正确调用。在我将 XML 反序列化到对象中的第二个示例中,如何让它工作?

【问题讨论】:

  • 你能发布 xaml 吗?你在哪里绑定?

标签: c# xml serialization inotifypropertychanged xmlserializer


【解决方案1】:

XML 序列化不能更新现有对象,它总是在您反序列化时创建一个新对象。因为它是一个新对象,所以还没有任何 PropertyChanged 的处理程序,因此不会触发该事件。

监听正在创建的对象的PropertyChanged 事件是没有意义的。你到底想做什么?

【讨论】:

  • 对,这在世界上都是有意义的。该设置是一个简单的服务器/客户端模型,通过 XML 相互更新。但我可以通过各种方式轻松解决这个问题。
【解决方案2】:

我完全同意 Thomas 的回答并补充几点建议:

如果您需要使用INotifyPropertyChanges,您绝对应该采用其他方式来反序列化对象。您可以使用InitializeFrom(string xml)UpdateFrom(string xml) 等实例方法。您创建一个对象,订阅PropertyChanged 事件,然后您在现有对象上调用UpdateFrom(xml)。因此,您将收到更改通知并保持现有对象处于活动状态。在这里,您可以通过以下方式实现整个事情:

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

我还会修改NotifyPropertyChanged 方法,以便在属性值未更改时不会触发。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多