Reputation: 723
i'm actually developping my first WPF application which must display all components of my computer in a treeview with hierarchical data.
Since yesterday i'm facing a little problem, i read tons of examples of treeview binding but I did not succeed with multiples types binding...
It must look like this :
My machine (level 0)
-----Keyboards⬇️(level 1)
--------Keyboard1⬇️(level 2)
--------Keyboard2⬇️(level 2)
-----OS⬇️(level 1)
-----CPU⬇️(level 1)
--------CPU1⬇️(level 2)
--------CPU2⬇️(level 2)
-----VideoCard⬇️(level 1)
---------VideoCard1⬇️(level 2)
---------VideoCard2⬇️(level 2)
I have a viewmodel with all my components device :
DeviceInfo.cs :
public class DeviceInfo
{
public string ComputerName { get; set; }
public Bios Bios { get; set; }
public ComputerSystem ComputerSystem { get; set; }
public List<Keyboard> Keyboards { get; set; }
public OperatingSystem OperatingSystem { get; set; }
public List<Processor> Processors { get; set; }
public List<VideoCard> VideoCards { get; set; }
}
Each component contain specific attribute, for example Keyboard.cs:
public class Keyboard
{
public string Description { get; set; }
public string DeviceID { get; set; }
}
I tried something like that for my treeview, i'm binding data in Mainwindow like this :
DeviceTree.ItemsSource = deviceInfos;
MainWindow.xaml :
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding Keyboards}">
<TextBlock Text="{Binding Description}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding OS}">
<TextBlock Text="{Binding Version}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="x:Type data:DeviceInfo" ItemsSource="{Binding VideoCard}">
<TextBlock Text="{Binding SerialNumber}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Actually It look like this in my treeview template:
"Model.DeviceInfo"
Every link of similar examples will be helpful for me. Thanks in advance
Upvotes: 2
Views: 2653
Reputation: 169218
A HierarchicalDataTemplate
supports only a single child property. It makes no sense to define three templates for the same type. Only of them can be applied at runtime anyway.
What you should do is to transform your DeviceInfo
class into a data-binding friendly view model class that has a single child property:
public class Item
{
public string Header { get; set; }
public IEnumerable<Item> Children { get; set; }
}
You would then bind the ItemsSource
property to an IEnumerable<Item>
of four Item
root objects, i.e. the level 1 keyboard, OS, CPU and VideoCard nodes.
Also note the sytax for setting the DataType
property to an actual type in XAML:
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Item}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Header}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Edit:
If the total number of levels is not dynamic, i.e. you always have a total of two levels, you could set or bind the ItemsSource
property to a new List<DeviceInfo>(1) { deviceInfos }
and add the "static" root levels to the TreeView
explicitly in your XAML markup:
<TreeView Margin="10" BorderThickness="2" BorderBrush="Black" Name="DeviceTree">
<TreeViewItem Header="Keyboards" ItemsSource="{Binding Keyboards}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem Header="Operating Systems" ItemsSource="{Binding OperatingSystem}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Version}" />
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<!-- + TreeViewItems for Processors and VideoCards -->
</TreeView>
Upvotes: 2
Reputation: 979
To make what you want you just have to put TreeViewItem in your primary TreeView. And if you want to up a level, you just have to add an ItemTemplate with a TreeViewItem inside. I give you an example for a simple object (Bios) and then for a List of object (Keyboards). The ItemSources of the TreeView is a list of DeviceInfo.
xaml :
<TreeView x:Name="MyTreeView">
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TreeViewItem Header="{Binding ComputerName}">
<TreeViewItem.Items>
<TreeViewItem Header="Bios">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Bios.Description}"/>
<TextBlock Text="{Binding Bios.Name}"/>
<TextBlock Text="{Binding Bios.Version}"/>
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="Keyboard" ItemsSource="{Binding Keyboards}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding DeviceID}">
<TextBlock Text="{Binding Description}"/>
</TreeViewItem>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeViewItem.Items>
</TreeViewItem>
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Upvotes: 1
Reputation: 31
This normally happens when WPF doesn't know how to display your model on the view. In your source code, you have defined the template which show each properties of the model in the TextBox. But you haven't applied them to your view.
So It just shows default ToString() of your model. That's why you only see the text "Model.DeviceInfo".
The following link would be helpful for you.
Upvotes: 0