WPF TreeView: Focus Selected Item - c#

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.

Related

How to add Scrolling to the HierarchicalDataTemplate items inside TreeView?

I want to add scrollviewer to every child inside TreeView. I can add scrollviewer for TreeView but I cannot apply scrollviewer to children elements.
Here is my example of the structure what currently using
<TreeView x:Name="test" ItemsSource="{Binding Root}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding TestTemplates}"
DataType="{x:Type vm1:TestTemplateViewModel}">
<Grid>
<DockPanel>
<TextBlock Text="{Binding TextBlock}"/>
<Image Source="/Images/Test.png"
Visibility="true">
</DockPanel>
</Grid>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

C# Hierarchical TreeView display extra level

how can i do that...
Field
--Crop year <-- property of crop. I want here an extra level for sorting like 2017 or 2018
---Crop
----Fertilizer
----Pesticide
... if "Crop year" is a datetime in crop. How can i get the extra level "year"?
<TreeView x:Name="tvFields" Margin="10" HorizontalContentAlignment="Stretch">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type entites:Field}" ItemsSource="{Binding Items}">
<StackPanel Orientation="Horizontal" Background="LightGreen">
<TextBlock Text="{Binding Name}" FontSize="16"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type entites:Crop}" ItemsSource="{Binding PestItems}">
<StackPanel Orientation="Horizontal" Background="LightBlue">
<TextBlock Text="{Binding Name}" FontSize="14" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type entites:Pesticide}" ItemsSource="{Binding PestItems}">
<StackPanel Orientation="Horizontal" Background="PaleGreen">
<TextBlock Text="{Binding Name}" FontSize="14" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type entites:Fertilizer}" ItemsSource="{Binding FertItems}">
<StackPanel Orientation="Horizontal" Background="Beige">
<TextBlock Text="{Binding Name}" FontSize="14" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Should I create an extra class for "Crop year"?
Lyror

Binding CollectionViewSource multilevel groups to nested HierarchicalDataTemplate

Only the the first level tree node is visible without any child, but my CollectionViewSource has groups with atleast one item. How can i bind the to child's ItemSource to Items property within each group.
<HierarchicalDataTemplate x:Key="myTemplate" >
<!-- Level 1 -->
<WrapPanel>
<CheckBox IsChecked="True" Margin="2,2,2,2" ></CheckBox>
<TextBlock Text="{Binding Name}" Margin="2,2,2,2" ></TextBlock>
</WrapPanel>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Items}">
<!-- Level 2 -->
<WrapPanel>
<CheckBox IsChecked="True" Margin="2,2,2,2" ></CheckBox>
<TextBlock Text="{Binding Name}" Margin="2,2,2,2" ></TextBlock>
</WrapPanel>
<DataTemplate>
<WrapPanel>
<CheckBox IsChecked="{Binding IsChecked}" Margin="2,2,2,2" ></CheckBox>
<TextBlock Text="{Binding Name}" Margin="2,2,2,2" ></TextBlock>
</WrapPanel>
</DataTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
<TreeView x:Name="TreeViewClaims" Grid.Row="1" Grid.Column="0" Margin="2,2,2,2" BorderThickness="0"
ItemsSource="{Binding GroupByView.View.Groups}"
ItemTemplate="{StaticResource myTemplate}">
</TreeView>
If all items should be displayed the same way you only have to specify one HierachicalDataTemplate and set the ItemsSource (property where your children are stored).
<HierarchicalDataTemplate x:Key="myTemplate"
ItemssSource="{Binding Items}"
TargetType="{x:Type FirstLevelViewModel}">
<WrapPanel>
<CheckBox IsChecked="True" Margin="2,2,2,2" ></CheckBox>
<TextBlock Text="{Binding Name}" Margin="2,2,2,2" ></TextBlock>
</WrapPanel>
</HierarchicalDataTemplate>
If you want a different view for each level you can implement a different viewmodel for each level and use the TargetType property in your HierachicalDataTemplate. The template will be automaically applied for rendering the viewmodel. But you cant use a HierachicalDataTemplate like you did in your first post.

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.

Use different datatemplate by binding to different TreeView selectedItem

I have built a WPF MVVM TreeView that shows different Elements.
BaseElement
- CatA
-- SubItemA
- CatB
-- SubItemB
Based on the class I would like to use a different data template.
for each type.
So far I can connect to the selected Item, but I'm not sure how to manage the different data templates.
public class SubItem
{
public string Type { get; set; }
public string Name { get; set; }
}
<StackPanel Grid.Column="2" DataContext="{Binding ElementName=myTreeView, Path=SelectedItem}">
<TextBox Text="{Binding Parent.Name}" />
<TextBox Text="{Binding Path=Name, Mode=TwoWay}" />
</StackPanel>
[Update Nov. 15]
<HierarchicalDataTemplate x:Key="L3Template" ItemsSource="{Binding L4Collection}" ItemTemplate="{StaticResource L4Template}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CategoryTemplate" ItemsSource="{Binding L3Collection}" ItemTemplate="{StaticResource L3Template}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="L1Template" ItemsSource="{Binding CategoryCollection}" ItemTemplate="{StaticResource CategoryTemplate}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
[/Update Nov. 15]
If the subitems are different classes, then it is rather simple: add datatemplates foreach class to the resource section.
If subitems need different templates based on the value of an enum prop, then you will need a datatemplateselector. This is a bit more cumbersome.
Assuming that you named your classes L1Class, L3Class en Category and local points to the namespace of these classes:
<TreeView ...>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:L3Class}" ItemsSource="{Binding L4Collection}" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Category}" ItemsSource="{Binding L3Collection}" >
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:L1Class}" ItemsSource="{Binding CategoryCollection}" >
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Note the use of the implicit datatemplates (no keys, but DataType!) in the resource section.
Just in case it will help someone else:
<ContentPresenter Grid.Column="2" Content="{Binding ElementName=myTreeView, Path=SelectedItem}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:L1ViewModel}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:CategoryViewModel}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:L3ViewModel}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:L4ViewModel}">
<StackPanel>
<TextBox Text="{Binding Parent.Name}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>

Categories