1

ObservableCollection 型の XML Serializable List があります。このコレクションに変更が加えられるたびに、シリアル化してから逆シリアル化する必要があるように、イベントを実装しています。

武器を追加、削除、および変更できる外部クラス (武器エディター) があります。削除ボタンが押されるとすぐに、この 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 オブジェクトがコレクションを直接操作している場合、それが問題です。WeaponsDatabase でカスタム メソッドを呼び出す必要があります。これにより、リクエストがコレクションに転送され、その直後に 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 に答える