HierarchicalDataTemplate what is it supposed to do? - c#

Basically i have a eeview that has a bunch of objects in it and the treeview needs to bind the same properties.
here is the code im using and it doesnt seem to work
<TreeView ItemsSource="{Binding Drives}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate>
<TreeViewItem Header="{Binding Name}" ItemsSource="{Binding Folders}" IsExpanded="{Binding IsExpanded, Mode=TwoWay}">
<TreeViewItem.ItemTemplate>
<HierarchicalDataTemplate>
<StackPanel>
<TreeViewItem Header="{Binding Name}" ItemsSource="{Binding Folders}" IsExpanded="{Binding IsExpanded,Mode=TwoWay}">
<TreeViewItem.ItemTemplate>
<HierarchicalDataTemplate>
<TreeViewItem Header="{Binding Name}" ItemsSource="{Binding Folders}" IsExpanded="{Binding IsExpanded,Mode=TwoWay}"/>
</HierarchicalDataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</StackPanel>
</HierarchicalDataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Basically when i get to the third level of treeview items i just get the Namespace+ObjectName.
Isnt the DataTemplate supposed to flow on and on ?

More like this
<TreeView ItemsSource="{Binding Drives}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Folders}">
<TextBlock Text="{Binding Name}"></TextBlock>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded,Mode=TwoWay}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

Related

WPF TreeView: Focus Selected Item

I've got a TreeView, that displays a Constant-Object which the User searched for. Those may have other Constant-Objects as a Parent or as Children. After selecting one of those objects in the TreeView, properties of this object are displayed below.
I already managed to select the searched object after displaying the treeview, now I need to set focus onto it.
Screenshots:
Current state
What I want to achieve
TreeView XAML Code:
<ContentControl x:Name="SelectedItemHelper" Content="{Binding SelectedConst, Mode=OneWayToSource}" Visibility="Collapsed"/>
<TreeView x:Name="constOutput" Margin="25,76,25,0" Height="130" HorizontalAlignment="Stretch" VerticalAlignment="Top" SelectedItemChanged="constOutput_SelectedItemChanged" ItemsSource="{Binding FoundConstants}" Style="{StaticResource lightGrayTV}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Constant}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Path=Name}" Style="{StaticResource txtTV}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Constant}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Path=Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Constant}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Path=Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Constant}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Path=Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Constant}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
The SelectedConst property is being set to the SearchedConst property at the end of the search.
private void SearchForConst(object value)
{
FoundConstants.Clear();
SearchedConstant = ConstantInfo.GetSearchedConstant(Input);
...
}
SelectedConst = SearchedConstant;
OnPropertyChange(nameof(SearchedConstant));
OnPropertyChange(nameof(FoundConstants));
}
How can I force the TreeView to expand and focus onto the SearchedConst/SelectedConst?
Then you need to make a reproducible example. A small project that replicates the problem.

How to bind an ObservableCollection to TreeView (hierarchical)

I've the following TreeView:
<Grid>
<TreeView Background="LightGoldenrodYellow" Grid.Row="3">
<TreeViewItem Header="Section 4">
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Total:" Width="150"/>
<TextBlock Text="{Binding Pool.Count}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Code" Width="150" />
<TextBlock Text="{Binding SecretViewModel.Codes}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem Header="Sub-Section 4.1">
<TreeViewItem>
<ListBox ItemsSource="{Binding Path=ListOfNames, UpdateSourceTrigger=PropertyChanged}" />
</TreeViewItem>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="Section 5">
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Color:" Width="150" />
<TextBlock Text="{Binding Colors}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
</TreeView>
</Grid>
How can I replace the Listbox and can bind the ObservableCollection to the TreeviewItem? It should look hierarchical.
I've tried to insert this code instead of the with the TextBox, but that does not work:
<HierarchicalDataTemplate>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ListOfNames, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
Not quite sure what exactly you are trying to achieve. You don't mean...
<TreeViewItem Header="Section 4">
<TreeViewItem Header="Sub-Section 4.1"
ItemsSource="{Binding Path=ListOfNames,
UpdateSourceTrigger=PropertyChanged}" />
</TreeViewItem>

WPF: Add ContextMenu to TreeView

For a second there I was proud that I finally managed to add a ContextMenu to a leaf in my TreeView, but then I realized it pops up on the wrong node.
My XAML:
<TreeView
Grid.Row="1"
Grid.Column="0"
x:Name="TvShowsTreeView"
ItemsSource="{Binding TvShows}"
SelectedItemChanged="TvShowsTreeViewOnSelectedItemChanged">
<!-- Season template -->
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Seasons}">
<TextBlock Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Hide"></MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
When I run this, I get a context menu on the TvShows, not on the Seasons.
I am close, right? :) Who can help me further here?
The correct XAML should be like this:
<TreeView
Grid.Row="1"
Grid.Column="0"
x:Name="TvShowsTreeView"
ItemsSource="{Binding TvShows}"
SelectedItemChanged="TvShowsTreeViewOnSelectedItemChanged">
<!-- TvShows template -->
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Seasons}">
<TextBlock Text="{Binding Name}" />
<!-- Seasons template -->
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate>
<TextBlock Text="{Binding Name}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Hide"></MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
The additional HierarchicalDataTemplate specifies the template for Seasons, which itself does not need to bind ItemSource because it does not contain nodes.

wpf TreeView HierarchicalDataTemplate related

I have a question related to HierarchicalDataTemplate. Is it possible to keep adding HierarchicalDataTemplate via code or there is no way to do that. I'm asking this because in my case later i don't know if i will need more child nodes than these i have now.
below you can see my treeview:
<TreeView Background="#FFF0F0F0" BorderBrush="#FFE5E2DB" IsEnabled="{Binding isAllesEnabled}" ItemsSource="{Binding LijstRechten, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Margin="0,0,0,0" Name="dgStamOverzichtGebruikerRechten" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
<TreeView.ItemTemplate>
<!-- Top Level -->
<HierarchicalDataTemplate ItemsSource="{Binding Childs}">
<CheckBox IsChecked="{Binding isChecked}" Content="{Binding naam}" />
<!-- 1st Child Level -->
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Childs}">
<CheckBox IsChecked="{Binding isChecked}" Content="{Binding naam}" />
<!-- 2nd Child Level -->
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Childs}">
<CheckBox IsChecked="{Binding isChecked}" Content="{Binding naam}" />
<!-- 3rd Child Level -->
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding isChecked}" Content="{Binding naam}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="Margin" Value="2"/>
<!--<Setter Property="IsSelected" Value="{Binding isSelected, Mode=TwoWay}"/>
<EventSetter Event="Selected" Handler="TreeViewSelectedItemChanged" />-->
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Thanks in advance!
For your problem, assuming all the childs are of same type.. just define one HierarchicalDataTemplate in your window's resources without any x:key and put the DataType which is type of your Child object...Your whole tree will populate..
<HierarchicalDataTemplate DataType="{local:YourParentType}"
ItemsSource="{Binding Childs}">
<CheckBox IsChecked="{Binding isChecked}" Content="{Binding naam}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{local:YourChildType}"
ItemsSource="{Binding Childs}">
<CheckBox IsChecked="{Binding isChecked}" Content="{Binding naam}" />
</HierarchicalDataTemplate>
here assuming local is the namespace (xmlns) in which your Child class is defined

How to display context menu for treeview item in a hierarchial data template in wpf

How to display context menu for tree view item in wpf using the hierarchical data template? How to display context menu only for CountryTemplate:
<HierarchicalDataTemplate x:Key="DispTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" Tag="{Binding Path=Tag}">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="BuildingTemplate" ItemsSource="{Binding Path=Building}" ItemTemplate="{StaticResource BuildingTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CityTemplate" ItemsSource="{Binding Path=City}" ItemTemplate="{StaticResource CityTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
You also can add the ContextMenu to any visual child in the data template, for instance:
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Header" Command="{Binding Command}"/> <!--This command should be in the data context (each country item)-->
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}"/>
</StackPanel>
</HierarchicalDataTemplate>
One of the reasons why context menus do not work as cleanly as they could is because by default, they are in a different visual tree to everything else, so the DataContext cannot be found.
The key insight is to create a <Style> that defines a context menu,
then attach that style to a target element, which hooks up the context
menu. This shifts the context menu into a visual tree that is lined up with the default DataContext you want.
First, create the style:
<UserControl.Resources>
<ResourceDictionary>
<!-- For the context menu to work, we must shift it into a style, which means that the context menu is now in a
visual tree that is more closely related to the current data context. All we have to do then is set the style,
which hooks up the context menu. -->
<Style x:Key="ContextMenuStyle" TargetType="{x:Type StackPanel}">
<Setter Property="ContextMenu" Value="{DynamicResource TreeViewContextMenu}"/>
</Style>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem Header="Test" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CmdDisplayDetailsGraph}"/>
</ContextMenu>
Then, hook the context menu up anywhere you want, without running into issues caused by different visual trees.
Example 1:
<HierarchicalDataTemplate DataType="{x:Type snapshot:Details}" ItemsSource="{Binding DetailsList}">
<StackPanel Orientation="Vertical" Style="{StaticResource ContextMenuStyle}">
<ContentPresenter Content="{Binding}" ContentTemplate="{Binding View.DefaultDataRowTemplate}" />
</StackPanel>
Example 2:
<DataTemplate DataType="{x:Type snapshot:InstrumentDetails}">
<StackPanel Orientation="Vertical" Style="{StaticResource ContextMenuStyle}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="{Binding Path=Country}" ItemContainerStyle="{StaticResource CountryTemplateItemContainerStyle}" ItemTemplate="{StaticResource CountryTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=RootName}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" />
</StackPanel>
</HierarchicalDataTemplate>
<Style x:Key="CountryTemplateItemContainerStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="ContextMenu" Value="{DynamicResource TreeViewContextMenu}"/>
</Style>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem .../>
</ContextMenu>
As you can see, you can add your contextmenu in the Itemcontainerstyle of the HierarchicalDataTemplate
Basically I came up with this
<HierarchicalDataTemplate x:Key="ChildTemplate">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" CommandParameter="{Binding CopyTag}">
</MenuItem>
<MenuItem Header="Paste" CommandParameter="{Binding PasteTag}">
</MenuItem>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.CopyPaste}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</StackPanel.ContextMenu>
<Image Source="/Images/Child.png" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" Style="{StaticResource TreeIconStyle}"/>
<TextBlock Text="{Binding Path=Label}" Style="{StaticResource TreeTextStyle}" ToolTip="{Binding Path=Description}" Tag="{Binding Path=Tag}">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
And have separate parameters for copy and paste to differentiate copy and paste in a single command.

Categories