Unable to bind model to TreeView - c#

This is a logging project, the Title provides the name of the item and the message logs each stage. Therefore, there are many Messages for each Title.
For the purpose of asking a question, I am simplifying my objects.
My Log class has 2 properties.
List<LogDetails>
string Title
And my LogDetails class has 1 property:
string Message
I am not able to bind the Message to my XAML. The Title binds as desired.
My xaml code:
<Window x:Class="BackUps.Logging.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myData="clr-namespace:BackUps.Logging"
Title="MainWindow"
Height="350"
Width="525">
<Grid>
<TreeView ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type myData:Log}"
ItemsSource="{Binding LogDetailsList}">
<TextBlock Text="{Binding Title}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type myData:LogDetails}">
<StackPanel>
<TextBlock Text="{Binding Message}" />
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
and my code behind
public MainWindow(List<Log> logs)
{
InitializeComponent();
this.DataContext = logs;
}
My result is (where you can see the missing entries):
This is the Auto's window, which shows the object I'm trying to bind.
What have I missed or doing wrong?

I had a similar problem in the past, and fixed it by (completely) changing the xaml to the form:
<Grid>
<TreeView ItemsSource="{Binding}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type myData:Log}"
ItemsSource="{Binding LogDetailsList}">
<TextBlock Text="{Binding Title}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type myData:LogDetails}>
<TextBlock Text="{Binding Message}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>

Related

WPF: The key is already defined in this scope

I'm working with TreeView and I want two ObservableCollections (KategorijeLekovi and KategorijeRadnici) to be shown under a node (which is an object of class Apoteka). I get this error: "The key is already defined in this scope." and it reffers to the second DataType="{x:Type local:Apoteka}". However, if I delete this DataType, I get a different error: "All objects added to an IDictionary must have a Key attribute or some other type of key associated with them."
<TreeView Grid.Column="0" Grid.Row="0" Name="trv1" >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Apoteka}" ItemsSource="{Binding KategorijeLekovi}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Naziv}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Apoteka}" ItemsSource="{Binding KategorijeRadnici}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Naziv}"/>
</StackPanel>
</HierarchicalDataTemplate>
...
Thank you all for answering, I managed to solve it with your help. Instead of having two ObservableCollections I made one, which had items from both KategorijeLekovi and KategorijeRadnici
You just need to use the x:key attribute
<HierarchicalDataTemplate x:Key="LekoviTemplate" DataType="{x:Type local:Apoteka}" ItemsSource="{Binding KategorijeLekovi}">
<HierarchicalDataTemplate x:Key="RadniciTemplate" DataType="{x:Type local:Apoteka}" ItemsSource="{Binding KategorijeRadnici}">
Then set it in the tree view,
<TreeView ItemTemplate="{StaticResource LekoviTemplate}" ...
or
<TreeView ItemTemplate="{StaticResource RadniciTemplate}" ...

WPF TreeView - Confusing data binding and style for child nodes

I am confused of WPFs data binding and style declaration for TreeViews, especially for child nodes.
My ViewModel contains an object with the following hierarchy:
- Component1
- SubcomponentA
- SubcomponentB
- Component2
- SubcomponentX
- SubcomponentY
- SubcomponentZ
I would like to modify the XAML file so I do not have to do anything within the .cs file.
This piece of code actually works:
<TreeView Name="tvComponent" ItemsSource="{Binding BpModule.BpComponentPrototypes.Elements}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding BpSubcomponents.Elements}">
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_run"></CheckBox>
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
However, I would like to create different styles for root and child nodes.
I tried different approaches with almost completely different XAML code. But the major problem was to describe the dependency of the binding of child nodes to their parent and so they remained empty during runtime.
Can you help me out?
Thank you.
In my opinion you can use the implicit DataTemplate mechanism (take a look here to the DataType property). In this way you can define more DataTemplates, each one of them "linked" to a specific Type.
<TreeView Name="tvComponent" ItemsSource="{Binding BpModule.BpComponentPrototypes.Elements}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:RootType}"ItemsSource="{Binding ...}">
...
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:ComponentType}" ItemsSource="{Binding BpSubcomponents.Elements}">
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_run"></CheckBox>
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:SubcomponentType}">
...
</DataTemplate>
</TreeView.Resources>
</TreeView>
Otherwise you can always use a DataTemplateSelector to create your own logic which chooses the right template for you.
Well, somehow I achieved to provide different designs for root and children nodes. Here is the XAML code:
<TreeView Name="tvSoftwareComponentPrototypes" ItemsSource="{Binding Path=BpModule.BpComponentPrototypes.Elements}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding BpSubcomponents.Elements}">
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_run"></CheckBox>
<Image Source="/Resources/SubComponent.png" Margin="5,0,3,0" />
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="cb_swc" Checked="cb_swc_Checked" Unchecked="cb_swc_Unchecked"></CheckBox>
<Image Source="/Resources/Component.png" Margin="5,0,3,0" />
<TextBlock Text="{Binding ShortName}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
And the next problem is that I cannot access the Checkboxes at runtime.
WPF freaks me out :/
EDIT:
Hold on .. actually this is quite easy by changing the checkbox to the following XAML code:
<CheckBox Name="cb_swc" IsChecked="{Binding Path=PropertyName, Mode=TwoWay}"/>

How to attach a different DataTemplate to the Same Hierarchical Template

Is it possible to attach different DataTemplates so that the children render differently to the same HierarchicalDataTemplate, which as I understand controls the View of the header
I am trying to do it without success::
<Window.Resources>
<DataTemplate
x:Key="ChildTemplate1">
<Label Content="Blah">
</DataTemplate>
<DataTemplate
x:Key="ChildTemplate2">
<Label Content="Blah2">
</DataTemplate>
<HierarchicalDataTemplate
x:Key="RootTemplate"
ItemTemplate={StaticResource ChildTemplate2}"
ItemsSource="{Binding Path=Children}">
<Label Content="Header">
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView ItemTemplate="{StaticResource RootTemplate}">
<TreeViewItem ItemTemplate="{StaticResource ChildTemplate1}"/>
</TreeView>
So again, what I am trying to do is override the DataTemplate set in HierarchicalDataTemplate(ChildTemplate2) with ChildTemplate1

Binding Dictionary<string,List<Class>> to TreeView

I have collection
Dictionary<string, List<Manager>> Stuff;
Manager is class with some properties.
I would like to bind this dictionary to TreeView or ListView like this:
Key as title, then list of Managers as children. For example:
Director (it's key from dictionary)
John (it's property Manager.Name)
Steve
Owner
Jack
I tried something like this:
<TreeView ItemsSource="{Binding Stuff}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate>
<TextBlock Foreground="Red" Text="{Binding Key}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
It shows me titles but I don't know how to make it further.
Or maybe it will be better to change collection and bind it in some other way.
EDIT
I unnecessarily complicated job with this dictionary. I created a class Stuff with property string Name;, and List<Managers> Managers;.
Use it in main class as ObservableCollection<Stuff> Stuff; and it works fine with this XAML:
<TreeView ItemsSource="{Binding Stuff}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Managers}">
<TextBlock Foreground="Red" Text="{Binding Name}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
So yeah using Dictionary wasn't best in this case.
Try this :
<TreeView Name="treeView1" ItemsSource="{Binding Stuff}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Value}">
<TextBlock Foreground="Red" Text="{Binding Path=Key}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Try this:
<TreeView ItemsSource="{Binding Stuff}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Values}">
<TextBlock Foreground="Red" Text="{Binding Key}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
However, I'd always recommend using an ObservableCollection<CustomDataType> as the ItemsSource because it just makes the whole job simpler. For more help with the HierarchicalDataTemplate, please see the HierarchicalDataTemplate Class page on MSDN.

Adding context menu to tree view by XAML only

Trying to add a context menu to a TreeView with just xaml code.
Tv Show
Season 1
Season n
The context menu should only show when I right click a Season node.
Is that possible? I know how to solve it with code behind, but I'd like to learn to use WPF as it is intended. I have trouble finding out if I should be able to solve this with using only xaml.
Current xaml:
<TreeView
Grid.Row="1"
Grid.Column="0"
ItemsSource="{Binding TvShows}" x:Name="TvShowsTreeView"
SelectedItemChanged="TvShowsTreeViewOnSelectedItemChanged">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="tvShows:TvShow" ItemsSource="{Binding Seasons}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Try using the ItemTemplate property of HierarchicalDataTemplate. It should look like this:
<HierarchicalDataTemplate DataType="tvShows:TvShow" ItemsSource="{Binding Seasons}">
<TextBlock Text="{Binding Name}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="TypeOfSeasonInYourApplication">
<TextBlock Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu>
<!-- Place MenuItems here -->
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
I actually didn't test that myself so please let me know if that works or not.

Categories