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>
Related
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.
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.
I have nested ListBoxes:
<ListBox Name="listbox" Padding="0,0,0,100" Loaded="listbox_Loaded" Foreground="Black">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" FontSize="30" FontWeight="Bold"/>
<ListBox ItemsSource="{Binding Categories}" Foreground="Black">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When I touch and drag items from inner listbox it plays scroll animation for this inner listbox. How to prevent this behavior? I need to scroll the outer listbox only, but the items from inner listbox still must be selectable.
Thank you!
Try to change Template of inner ListBox to be only ItemsPresenter. This will remove ScrollViewer which is normally part of that template:
<ListBox ItemsSource="{Binding Categories}" Foreground="Black">
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<ItemsPresenter/>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
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.
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>