简体   繁体   English

为什么我的ObservableCollection序列化不起作用?

[英]Why my ObservableCollection serialization doesn't work?

I'm trying to serialize and deserialize this ObservableCollection: 我正在尝试对此ObservableCollection进行序列化和反序列化:

public class DataCollection : ObservableCollection<Data>
{
}

public class Data : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool? _enabled;

    public string Name { get; set; }
    public bool? Enabled 
    {
        get { return _enabled; }
        set { _enabled = value; NotifyPropertyChanged("Enabled"); }
    }

    public Data(string name, bool? enabled)
    {
        this.ScriptName = name;
        this.Enabled = enabled;
    }

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

Using this class (as in the What is the easiest way to save an Observable collectin of object to an XML file? example): 使用此类(例如,将对象的Observable对象集合保存到XML文件的最简单方法什么? ):

class UserPreferences
{
    private DataCollection _dataLst;
    private const string _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);
        }
    }
}

And here is how I call it from my app: 这是我从应用程序中调用的方式:

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

But it creates empty file and hangs up (even without exceptions, just app window becomes black and doesn't response) in the line 但是它会创建一个空文件并挂起(即使没有异常,只是应用程序窗口变黑并且没有响应)

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

After a little research it seems that there are problems when serializing ObservableCollection<T> . 经过一些研究,序列化ObservableCollection<T>似乎有问题。 See this blog post for more information. 请参见博客文章以了解更多信息。

In summary: 综上所述:

The problem is that the events have not been marked as non-serialized. 问题在于事件没有被标记为非序列化。 Therefore, whenever you try to serialize an instance of ObservableCollection, you will also be attempting to serialize any event handlers. 因此,每当您尝试序列化ObservableCollection的实例时,您还将尝试序列化任何事件处理程序。 When you're using the collection for its primary scenario (data binding), you will have WPF controls attached to the events. 将集合用于主要场景(数据绑定)时,将在事件上附加WPF控件。

(Kent Boogaart) (肯特·布加(Kent Boogaart))

Your Data class will also suffer from similar problems; 您的Data类也将遭受类似的问题; update your PropertyChanged event like so: 像这样更新您的PropertyChanged事件:

[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;

As well as the updates already mentioned by other people, your Data class should also be marked as Serializable . 除了其他人已经提到的更新之外,您的Data类也应标记为Serializable

  1. Your Data class must have a parameter less constructor, otherwise XmlSerializer will never be able to create instance of Data. 您的Data类必须具有较少参数的构造函数,否则XmlSerializer将永远无法创建Data实例。
  2. Instead of storing DataCoollection, you should store and retrieve Data[], it's easier without having to do anything else. 您应该存储和检索Data []而不是存储DataCoollection,这样就无需执行任何其他操作就更容易了。
  3. While storing, you can call ToArray method to get Data[] and use typeof(Data[]) for serializer. 在存储时,可以调用ToArray方法来获取Data []并使用typeof(Data [])进行序列化。
  4. While reading you can read the array and add items into your collection. 读取时,您可以读取数组并将项目添加到集合中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM