【问题标题】:Why my ObservableCollection serialization doesn't work?为什么我的 ObservableCollection 序列化不起作用?
【发布时间】:2012-08-26 21:24:18
【问题描述】:

我正在尝试序列化和反序列化这个 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));
    }
}

使用这个类(如What is the easiest way to save an Observable collectin of object to an XML file? 示例):

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

这是我从我的应用程序中调用它的方式:

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

但它会创建空文件并在行中挂断(即使没有例外,只是应用程序窗口变黑并且没有响应)

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

【问题讨论】:

  • [Serializable] 添加到您的DataCollection
  • @nemesv 它没有帮助,仍然是同样的问题。

标签: c# .net wpf xml xml-serialization


【解决方案1】:

经过一番研究,似乎序列化ObservableCollection&lt;T&gt;时存在问题。有关详细信息,请参阅 this 博客文章。

总结:

问题是事件没有被标记为非序列化。因此,每当您尝试序列化 ObservableCollection 的实例时,您也将尝试序列化任何事件处理程序。当您将集合用于其主要场景(数据绑定)时,您会将 WPF 控件附加到事件。

(肯特·布加特)

您的Data 班级也会遇到类似问题;像这样更新您的 PropertyChanged 事件:

[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;

除了其他人已经提到的更新,你的Data类也应该标记为Serializable

【讨论】:

  • 我在某处读到事件问题已在 .NET 4.0 中得到修复。当我向 Data 类添加无参数构造函数时,它似乎可以工作。
  • 我将把这个答案留在这里,因为这可能对使用早期版本框架的人有所帮助。您的数据类仍需要按照建议更新其属性更改事件,否则它还将尝试序列化任何订阅的内容。
  • 2016 年 4 月 - 只需确认这在当前 .NET 中不是问题 - ObservableCollection 是可序列化的,无需特殊处理。甚至可以在 Xamarin.Forms 跨平台解决方案中的 PCL 项目中工作。
  • [Serializable][Serializable()]有区别吗?
【解决方案2】:
  1. 您的 Data 类必须有一个无参数构造函数,否则 XmlSerializer 将永远无法创建 Data 实例。
  2. 您应该存储和检索 Data[],而不是存储 DataCoollection,这样更容易,无需执行任何其他操作。
  3. 存储时,可以调用 ToArray 方法获取 Data[] 并使用 typeof(Data[]) 进行序列化。
  4. 在阅读时,您可以读取数组并将项目添加到您的集合中。

【讨论】:

  • 谢谢,在我添加了一个无参数构造函数后,它似乎可以工作了。但是你的意思是我应该“存储和检索 Data[] 而不是存储 DataCollection?为什么它更容易?我使用 ObservableCollection 作为 ListBox ItemsSource 绑定 (WPF)。
  • 有时我们遇到问题并且确实需要额外的编码,我不记得究竟是什么问题,但我们避免序列化集合,我们总是序列化为数组。因为在旧版本的 .NET 中也可以轻松访问序列化数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
相关资源
最近更新 更多