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





5.00/5 (5投票s)
关于 TreeView 内容的序列化/反序列化的技巧与窍门(使用 XML)
引言
本文介绍了如何使用 XML 保存和重新加载 WPF/MVVM TreeView 的内容。
背景
最近一篇关于 C#/VB.Net 中 XML 读写的文章 [5] 讨论了在 .Net 中使用 XML 的不同选项。本文在此基础上,提供了一个实用的示例,其中包含一个类似于 Visual Studio 中 Solution Explorer 工具窗口的演示应用程序。
使用代码
您应该可以直接下载附件的示例,在 VS 2017 Community 中打开项目,恢复 nuget 包,然后编译运行(如果有任何问题,请使用下方的论坛)。
以下截图显示了演示应用程序的主窗口
您可以使用上下文菜单(见上文)来排列 TreeView 中的项目。使用“保存”按钮(见下文)来保存 TreeView 的内容。
该应用程序显示一个标准的“保存”对话框,其中包含 2 种文件模式选项
- *.solxml
- *.solsqlite
如果您偏好二进制关系数据格式(如 [4] 中所述),请选择 *.solsqlite 选项。如果您想保存和加载 TreeView 的内容为经典的纯 XML,请选择 *.solxml 选项。
数据重新加载的流程与保存类似,只是使用“加载”按钮。
下面的序列图展示了在保存 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
接口在此处的运作方式(如果您感到困惑)。否则,如果您觉得有什么重要的内容缺失或完全错误,欢迎随时留下反馈并提问。