How to bind to child element property in TreeView - c#

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>

Related

How do Create a Checkbox Element in WPF with Image and Some Text

I want to design a Control Similar to this, where to the left corner would be Some Text and right corner will have Checkbox mark.
I tried doing something like this.
<ListView x:Name="MyListView">
<ListView.ItemTemplate>
<DataTemplate x:Name="DoubleLineDataTemplate" >
<CheckBox IsChecked="{Binding IsChecked}">
<StackPanel Orientation="Horizontal">
<Image VerticalAlignment="Center" Source="{Binding Img}">
</Image>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="12,0,0,0">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</StackPanel>
</CheckBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
But the output isn't what I want.
you can put Image, text and checkbox in a single Grid and stick text and checkbox to corners:
<ListView x:Name="MyListView">
<ListView.ItemTemplate>
<DataTemplate x:Name="DoubleLineDataTemplate" >
<Grid>
<Image VerticalAlignment="Center" Source="{Binding Img}"/>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5"/>
<CheckBox IsChecked="{Binding IsChecked}"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="5"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

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.

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.

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