65.9K
CodeProject 正在变化。 阅读更多。
Home

C#/VB.Net 高级 WPF TreeView 系列文章(共 n 部分)- 第 5 部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2017 年 12 月 27 日

CPOL

4分钟阅读

viewsIcon

38698

downloadIcon

783

关于 TreeView 内容的序列化/反序列化的技巧与窍门(使用 XML)

引言

本文介绍了如何使用 XML 保存和重新加载 WPF/MVVM TreeView 的内容。

背景

最近一篇关于 C#/VB.Net 中 XML 读写的文章 [5] 讨论了在 .Net 中使用 XML 的不同选项。本文在此基础上,提供了一个实用的示例,其中包含一个类似于 Visual Studio 中 Solution Explorer 工具窗口的演示应用程序。

使用代码

您应该可以直接下载附件的示例,在 VS 2017 Community 中打开项目,恢复 nuget 包,然后编译运行(如果有任何问题,请使用下方的论坛)。

以下截图显示了演示应用程序的主窗口

Sample Screenshot

您可以使用上下文菜单(见上文)来排列 TreeView 中的项目。使用“保存”按钮(见下文)来保存 TreeView 的内容。

Sample Screenshot

该应用程序显示一个标准的“保存”对话框,其中包含 2 种文件模式选项

  • *.solxml
  • *.solsqlite

如果您偏好二进制关系数据格式(如 [4] 中所述),请选择 *.solsqlite 选项。如果您想保存和加载 TreeView 的内容为经典的纯 XML,请选择 *.solxml 选项。

Sample Screenshot

数据重新加载的流程与保存类似,只是使用“加载”按钮。

下面的序列图展示了在保存 XML 数据过程中,主要对象之间的交互流程

MainWindow.xaml 中单击按钮会调用 AppViewModel 类中绑定的 ICommand SaveSolutionCommand 属性,该属性会显示标准的“文件保存”对话框,让用户选择文件名、位置和格式。

AppViewModel.Save_SolutionCommand_Async() 方法会将 ViewModel 转换为 Model,这与之前为保存为 SQLite 数据格式所讨论的内容相同 [4]

生成的树模型(上图所示)由**仅内部类**组成。也就是说,SolutionLibModels 库外部的任何人只能使用相关的接口和 Factory 类来与这些数据项进行交互。

转换后的 Model 被传递给 SolutionLibModels.Xml.Storage.WriteXmlToFile() 方法,该方法通过 DataContractSerializer IXmlSerializable 接口实现实际的序列化。

public static void WriteXmlToFile(string filename, ISolutionModel rootModel)
{
  XmlWriter xmlWriter = null;
  try
  {
    var fileStream = new FileStream(filename, FileMode.Create);
    xmlWriter = XmlWriter.Create(fileStream, new XmlWriterSettings
    {
        Indent = true,
        IndentChars = "  ",
        CloseOutput = true
    });

    var dataContractSerializer = new DataContractSerializer(typeof(SolutionModel));
    dataContractSerializer.WriteObject(xmlWriter, rootModel);
  }
  finally
  {
    if (xmlWriter != null)
        xmlWriter.Close();
  }
}

WriteXmlToFile() 方法与我们之前加载和保存 XML 所使用的方法基本相同 [5],如 DataContractSerializer_V1.zip 示例所示。Storage 类中的上述代码会评估 ModelRoot 并检测到 IXmlSerializable 接口。因此,DataContractSerializer 会调用 ModelRoot.WriteXml() 方法,该调用会处理所有其他树视图项的 ...WriteXml() 方法,如果它们按照之前讨论的方式进行处理的话 [5]

调用所有 IXmlSerializable 方法的最终结果应该是一个 XML 文件,该文件在单击“加载”按钮时应该可以被加载。

加载 XML 数据的处理过程非常相似,因此在此省略详细解释。

结论

上述示例还解释了为什么需要进行 ViewModel 和 Model 之间的转换,这看似额外的(无用的)负担。我们注意到,附加的实现中,ViewModel 对 XML 序列化器和/或 SQLite 存储解决方案没有直接引用。这些引用只在实现 Model 的库中可见。因此,我们可以声称 Model/ViewModel 的转换保证了关注点的分离,从而确保了代码的健康和简化开发。

就是这样。这基本上就是我关于通过 XML 加载和保存 WPF TreeView 内容想说的。本文介绍的示例实现了从 [5] 中学到的经验,因此您至少应该阅读有关 DataContractSerializer_V1.zip 示例的部分,以理解 IXmlSerializable 接口在此处的运作方式(如果您感到困惑)。否则,如果您觉得有什么重要的内容缺失或完全错误,欢迎随时留下反馈并提问。

参考文献

© . All rights reserved.