1

我有一个 XML 可序列化列表,它的类型为 ObservableCollection。我实现了一个事件,因此只要对此集合进行更改,就应该对其进行序列化,然后反序列化。

有一个外部类(武器编辑器)可以添加、删除和修改武器。只要按下删除按钮,就会来到这个 WeaponsDB 类来收集 ObservableCollection。但是,它会在我的 CollectionChanged 事件执行之前刷新 ObservableCollection 中的内容。

在任何其他类获得最新数据之前,如何确保 CollectionChanged 事件已完全执行并且一切都是最新的?

public class WeaponDatabase
{
    [XmlArray("Weapons"), XmlArrayItem(typeof(Weapon), ElementName = "Weapon")]
    public ObservableCollection<Weapon> Weapons = new ObservableCollection<Weapon>();

    private string path = @"Inventory\WeaponsDB.xml";

    public WeaponDatabase()
    {
        DeserializeData();
        Weapons.CollectionChanged += Weapons_CollectionChanged;
    }

    void Weapons_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        SerializeData();
        DeserializeData();
    }

    public void SerializeData()
    {
        XmlSerializer Serializer = new XmlSerializer(typeof(ObservableCollection<Weapon>));
        TextWriter textWriter = new StreamWriter(path);
        Serializer.Serialize(textWriter, Weapons);
        textWriter.Close();
    }

    public void DeserializeData()
    {
        XmlSerializer Serializer = new XmlSerializer(typeof(ObservableCollection<Weapon>));
        StreamReader reader = new StreamReader(path);
        Weapons = (ObservableCollection<Weapon>)Serializer.Deserialize(reader);
        reader.Close();
    }
}
4

2 回答 2

3

我还没有使用 ObservableCollection,所以我有可能是一个触手可及的人,但是嘿。

很可能,您的弱点是您正在向后看。CollectionChanged 应该被触发以让访问集合的外部对象知道集合已更新,而不是用于更新实际集合(通过将其转储到文件或从 XML 文件重建)。

以机智:

这个外部类应该有一个这样的设置:

    public class WeaponsEditor
    {
        private WeaponsDatabase DB;
        public WeaponsEditor()
        {
            DB = new WeaponsDatabase();
            DB.CollectionChanged += CollectionChanged;
        }

        private object CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            // respond to the updated database
        }
    }

基本上,CollectionChanged 事件是让其他对象响应更改的集合,而不是让您的类进行更新。如果 Weapons Editor 对象直接操作集合,那是你的问题;您应该让它调用 Wea​​ponsDatabase 中的自定义方法,该方法会将请求转发到集合,然后立即调用 Serialize/Deserialize 方法。

于 2013-08-07T04:21:56.303 回答
1

您需要将INotifyPropertyChanged接口添加到WeaponDatabase(我说使用该接口而不是自定义事件,这样BindingSources就会自动使用它)

public class WeaponDatabase : INotifyPropertyChanged
{
    [XmlArray("Weapons"), XmlArrayItem(typeof(Weapon), ElementName = "Weapon")]
    public ObservableCollection<Weapon> Weapons {get; private set;}

    private string path = @"Inventory\WeaponsDB.xml";

    public event PropertyChangedEventHandler PropertyChanged;

    public WeaponDatabase()
    {
        Weapons = new ObservableCollection<Weapon>();
        DeserializeData();
        Weapons.CollectionChanged += Weapons_CollectionChanged;
    }

    private void RaiseWeaponsChanged()
    {
        var temp = this.PropertyChanged;
        if(temp != null)
            temp(this, new PropertyChangedEventArgs("Weapons"));
    }

    void Weapons_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        SerializeData();
        DeserializeData();
        RaiseWeaponsChanged()
    }

    //Snip
}

现在其他类可以订阅该WeaponDatabase.PropertyChanged事件并在集合更改和反序列化完成时收到通知。

于 2013-08-07T04:40:32.417 回答