This article shows how the content of a WPF/MVVM TreeView can be saved and re-loaded with XML.
A recent article  on Reading and Writing XML in C#/VB.Net discussed different options for using XML in .Net. This article builds on this base and gives a practical example with a demo application that is similar to the Solution Explorer Tool Window in Visual Studio.
Using the code
You should be able to just download the attached sample, open the project in VS 2017 Community, restore nuget packages, compile, and run (use the Forum below, if you have any questions).
The following screenshot shows the main window of the demo application:
You can use the context menu (see above) to arrange the items in the tree view. Use the Save button (see below) to save the content of the tree view.
The application shows a standard Save dialog that contains 2 file pattern options:
Choose the *.solsqlite option, if you prefer a binary relational data format as discussed in . Choose the *.solxml option, if you want to save and load the contents of the tree view in good old plain XML.
Reloading data is implemented with the same workflow but using the Load button.
The sequence diagram below shows the workflow between the main objects participating in the interaction for saving the XML data:
The button click in
MainWindow.xaml invokes the bound
ICommand SaveSolutionCommand property in the
AppViewModel class, which in turn displays the standard file save dialog to let the user choose a file name, location, and the format.
AppViewModel.Save_SolutionCommand_Async() method then converts the viewmodel into a model as previously discussed for saving in the SQLite data format :
The resulting tree model (shown above) is composed out of internal classes only. That is, everyone outside of the
SolutionLibModels library can only use the associated interfaces and the
Factroy class to interact with these data items.
The converted model is then handed over to the
SolutionLibModels.Xml.Storage.WriteXmlToFile() method that implements the actual serialization via
public static void WriteXmlToFile(string filename, ISolutionModel rootModel)
XmlWriter xmlWriter = null;
var fileStream = new FileStream(filename, FileMode.Create);
xmlWriter = XmlWriter.Create(fileStream, new XmlWriterSettings
Indent = true,
IndentChars = " ",
CloseOutput = true
var dataContractSerializer = new DataContractSerializer(typeof(SolutionModel));
if (xmlWriter != null)
WriteXmlToFile() method is pretty much the same method that we have previously used to load and save XML  as shown in the DataContractSerializer_V1.zip sample. The above code in the
Storage class evaluates the
ModelRoot and sees the
IXmlSerializable interface. So, the
DataContractSerializer invoces the
ModelRoot.WriteXml() method and this invocations processes' all other
...WriteXml() methods of all other tree view items, if they are processed as previously discussed .
The result of the invocation of all the
IXmlSerializable methods is hopefully an XML file that should be loadable upon a click on the Load button.
The processing for the loading of the XML Data is very similar - so I leave the explicit explanation out of here.
The above sample also shows an interesting reason for the seemingly additional (useless) burden of having to convert between viewmodel and models. We note that the attached implementation does not have a direct reference from the viewmodel to an XML serializer and/or SQLite storage solution. These references are only visible on the library that implements the model. We can. thus, claim that the model/viemodel conversion ensure a separation of concerns, which in turm will ensure a healthy and simplified development of this code.
Thats it. This is pretty much what I wanted to say about loading and saving WPF tree view content via XML. The sample presented in this article implements the lessons learned from , so you should at least read the section about the DataContractSerializer_V1.zip sample in order to understand how the
IXmlSerializable interface works here (if you got lost). Otherwise, you are always welcome to leave feedback and ask questions if you feel like something important is missing or plain wrong.