Binding CollectionViewSource multilevel groups to nested HierarchicalDataTemplate - c#

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.

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 to child element property in TreeView

I have tree view in wpf, it looks like:
CategoryName1
Image1 ChildElementName1
Image2 ChildElementName2
Image3 ChildElementName3
CategoryName2
Image1 ChildElementName1
Image2 ChildElementName2
Image3 ChildElementName3
...
How i can use in my CategoryNames image from child[0]? I tried binding on element name, but this is not working.
My xaml code is:
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Items}">
<StackPanel Orientation="Horizontal">
<Image Source="here i dont know how to do properly"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="img"
Source="{Binding Path=ImageSource}"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
The solution is simple, but i dont know how correct it is
We can refer like this
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Items}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Items[0].ImageSource}"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="img"
Source="{Binding Path=ImageSource}"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>

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

WPF TreeView selecting next or previous items in code

I would like to have previous/next arrows to select items in the treeview. I have 3 parent nodes that have childs. The parent nodes won't do anything so if I was at the end of the childs in parent node 1, I want the next arrow to select the 1st child in parent node 1. Same with the reverse if on the fist node of parent 2 and clicking previous will take me to the last child or parent node 1.
xaml of the treeview currently
<TreeView x:Name="tvMessages" HorizontalAlignment="Left" Height="363" Margin="10,37,0,0" VerticalAlignment="Top" Width="312" SelectedItemChanged="tvMessages_SelectedItemChanged">
<TreeViewItem x:Name="itemsCritical">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="/FlashSystem/Images/Critical.png" Height="16px" Width="16px"/>
<TextBlock Margin="5,0" Text="Critical"/>
</StackPanel>
</TreeViewItem.Header>
<TreeViewItem.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="/FlashSystem/Images/Message.png" Width="16px" Height="16px"/>
<TextBlock Margin="5,0" Text="{Binding Description}"/>
<TextBlock Text="{Binding ID}" Visibility="Hidden"/>
<TextBlock Text="{Binding Specility}" Visibility="Hidden"/>
<TextBlock Text="{Binding IssuedDate}" Visibility="Hidden"/>
<TextBlock Text="{Binding Severity}" Visibility="Hidden"/>
</StackPanel>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem x:Name="itemsAlert">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="/FlashSystem/Images/Alert.png" Height="16px" Width="16px"/>
<TextBlock Margin="5,0" Text="Alert"/>
</StackPanel>
</TreeViewItem.Header>
<TreeViewItem.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="/FlashSystem/Images/Message.png" Width="16px" Height="16px"/>
<TextBlock Margin="5,0" Text="{Binding Description}"/>
<TextBlock Text="{Binding ID}" Visibility="Hidden"/>
<TextBlock Text="{Binding Specility}" Visibility="Hidden"/>
<TextBlock Text="{Binding IssuedDate}" Visibility="Hidden"/>
<TextBlock Text="{Binding Severity}" Visibility="Hidden"/>
</StackPanel>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem x:Name="itemsInformational">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="/FlashSystem/Images/Info.png" Height="16px" Width="16px"/>
<TextBlock Margin="5,0" Text="Informational"/>
</StackPanel>
</TreeViewItem.Header>
<TreeViewItem.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="/FlashSystem/Images/Message.png" Width="16px" Height="16px"/>
<TextBlock Margin="5,0" Text="{Binding Description}"/>
<TextBlock Text="{Binding ID}" Visibility="Hidden"/>
<TextBlock Text="{Binding Specility}" Visibility="Hidden"/>
<TextBlock Text="{Binding IssuedDate}" Visibility="Hidden"/>
<TextBlock Text="{Binding Severity}" Visibility="Hidden"/>
</StackPanel>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</TreeView>
I would try to simulate the key down event and see if it works.
If you simulate the arrow key down event the TreeViewItem will do the job for you. It will either expand itself or move the selection to its Children[0] item.
Internally TreeViewItem listens to KeyDown and it works with ItemContainerGenerator to find the Children[0] item.
Here is how you can simulate arrow key in WPF:
var backKey = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, Key.Back);
backKey.RoutedEvent = Keyboard.KeyDownEvent;
InputManager.Current.ProcessInput(backKey);
You wont need the back key you will need the right or left arrow still you will need InputManager to process input :)

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