Pourquoi ma sérialisation ObservableCollection ne fonctionne-t-elle pas?

J’essaie de sérialiser et de désérialiser cette ObservableCollection:

public class DataCollection : ObservableCollection { } public class Data : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private bool? _enabled; public ssortingng Name { get; set; } public bool? Enabled { get { return _enabled; } set { _enabled = value; NotifyPropertyChanged("Enabled"); } } public Data(ssortingng name, bool? enabled) { this.ScriptName = name; this.Enabled = enabled; } private void NotifyPropertyChanged(ssortingng property) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property)); } } 

Utilisation de cette classe (comme dans l’exemple Quelle est la méthode la plus simple pour enregistrer une collection d’object Observable dans un fichier XML? ):

 class UserPreferences { private DataCollection _dataLst; private const ssortingng _dataLstFileName = "Data.xml"; public DataCollection DataLst { get { return _dataLst; } set { _dataLst = value; } } public UserPreferences() { Load(); } public void Load() { if (File.Exists(_dataLstFileName)) { using (var reader = new StreamReader(_dataLstFileName)) { var xs = new XmlSerializer(typeof(DataCollection)); _dataLst = (DataCollection) xs.Deserialize(reader); } } else { _dataLst = new DataCollection(); } } public void Save() { using (var writer = new StreamWriter(_dataLstFileName)) { var xs = new XmlSerializer(typeof(DataCollection)); xs.Serialize(writer, _dataLst); } } } 

Et voici comment je l’appelle depuis mon application:

 public partial class MainWindow : Window { private DataCollection DataLst; ... private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { var userPrefs = new UserPreferences(); userPrefs.DataLst = DataLst; // DataList isn't null and contains correct data userPrefs.Save(); } } 

Mais il crée un fichier vide et raccroche (même sans exception, seule la fenêtre de l’application devient noire et ne répond pas) dans la ligne

 var xs = new XmlSerializer(typeof(DataCollection)); 

  1. Votre classe Data doit avoir un constructeur sans paramètre, sinon XmlSerializer ne pourra jamais créer d’instance de Data.
  2. Au lieu de stocker DataCoollection, vous devriez stocker et récupérer des données [], c’est plus facile sans rien faire d’autre.
  3. Pendant le stockage, vous pouvez appeler la méthode ToArray pour obtenir Data [] et utiliser typeof (Data []) pour le sérialiseur.
  4. Pendant la lecture, vous pouvez lire le tableau et append des éléments à votre collection.

Après quelques recherches, il semble que la sérialisation de ObservableCollection pose des problèmes. Voir ce blog pour plus d’informations.

En résumé:

Le problème est que les événements n’ont pas été marqués comme non sérialisés. Par conséquent, chaque fois que vous tentez de sérialiser une instance de ObservableCollection, vous tentez également de sérialiser des gestionnaires d’événements. Lorsque vous utilisez la collection pour son scénario principal (liaison de données), des contrôles WPF sont associés aux événements.

(Kent Boogaart)

Votre classe de Data souffrira également de problèmes similaires; mettez à jour votre événement PropertyChanged comme suit:

 [field: NonSerialized] public event PropertyChangedEventHandler PropertyChanged; 

En plus des mises à jour déjà mentionnées par d’autres personnes, votre classe de Data doit également être marquée comme étant Serializable .