As a learning exercise I am trying to load a WPF TreeView control with XML data from a file and using only XAML. I am using this example as a guide.
I struggled for two days to get it to work in Visual Studio 2022 with a project type of WPF Desktop and .NET 6.0 (TargetFramework=net6.0-windows
). Well, I couldn’t get it to work. On a lark I created a new project of type WPF .NET Framework 4.7.2 (TargetFramework=v4.7.2
). This worked.
BTW: For the .NET 6.0 project, the data showed up in the designer, but not at runtime.
I am quite confused with all of the versions of .NET. I am going to write a small application in C#/WPF for Windows 10, and I don’t know which type of project to create. I thought .NET 6.0 was the future. Will someone kindly explain why the code doesn’t work, and advise me on how I should proceed? Thank you very much.
The code:
<Window x:Class="XMLTreeView.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:XMLTreeView"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<XmlDataProvider x:Key="XmlData" Source="Tree.xml" XPath="Folders"/>
<HierarchicalDataTemplate x:Key="ItemTemplate" ItemsSource="{Binding XPath=./Folder}">
<TextBlock Text="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView Width="400"
ItemsSource="{Binding Source={StaticResource XmlData}}"
ItemTemplate="{Binding Source={StaticResource ItemTemplate}}"/>
</Grid>
</Window>
The file:
<Folders>
<Folder Name="Adolph Henselt">
<Folder Name="Henselt Piano Works" />
</Folder>
<Folder Name="Alexander Borodin">
<Folder Name="String Quartet Nos. 1 and 2" />
<Folder Name="Symphony No. 2, Polovtsian Dances" />
</Folder>
....
</Folders
Regards,
Bob
2
Answers
I figured it out with the help of Anthony's post. It got me thinking about Visual Studio itself. What I found was:
After I created the .NET Framework 4.7.2 project, I added the XML file and set the option Copy to Output Directory as "Copy if newer". I did the same thing when I created the .NET 6.0 project.
But what I overlooked was that by default the .NET Framework project set the Build Action to Resource, and the .NET 6.0 project set it to None. When I changed the Build Action to Resource, the .NET 6.0 project worked without any other changes.
This was just a learning exercise. Actually, the TreeView will be populated with CLR objects using the MVVM pattern as you suggested Anthony.
Thank you very much.
Bob
I was able to get the demo working but had to pay attention to a few things:
At first under the XAML Binding Failures tab in Visual Studio I got an error stating "XmlDataProvider cannot load asynchronous document from Source because of load or parse error in XML… Cannot locate resource ‘tree.xml’"
Hard coding the path to the XML worked as pictured below:
While mock data loaded from an XML is great for coming up with a prototype, its actually not very common in real life because of its static nature.
If this is your first foray into using WPF I would suggest you familiarize yourself with MVVM patterns and data binding in XAML, (Please for the love of all things holy do not use code behind) https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/?view=netdesktop-6.0
As for .Net6 and its future. Yes! It is meant to bring us closer to the holy grail of write once, run everywhere. It is not without warts, but knowing how to separate code from UI, by applying the same layered architecture principles everyone is preaching will pay dividends in long term maintainability.