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
Related
I am new to WPF/XAML so I am stuck in one problem is it possible that if I create one TEMPLATE of combobox in UI and what if is it possible to use one ComboBox to render multi-item sources? For example, I have two item sources A and B and in XAML I have one common template. So is it possible that I can create two different ComboBox in UI for A and B from single template?
I am using below template for creation
<ComboBox x:Name="comboboxtemplate" ItemsSource="{Binding CboItemsource}" SelectedItem="{Binding comboboxSelecteditem, Mode=TwoWay}"
Visibility="{Binding ShowCombobox, UpdateSourceTrigger=PropertyChanged}" Width="{Binding ComboboxWidth, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding FieldValueIsEditable, UpdateSourceTrigger=PropertyChanged}"
IsTextSearchCaseSensitive="False"
IsTextSearchEnabled="True"
TextSearch.TextPath="Description">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Code}" Width="0"/>
<TextBlock Text= "{Binding Description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You could create a style that you apply to both ComboBoxes, .e.g.:
<Window x:Class="WpfApplication1.Window1"
...>
<Window.Resources>
<Style x:Key="cmbStyle" TargetType="ComboBox">
<Setter Property="Visibility" Value="{Binding ShowCombobox, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsEnabled" Value="{Binding FieldValueIsEditable, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsTextSearchEnabled" Value="True" />
<!-- ... -->
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Code}" Width="0"/>
<TextBlock Text= "{Binding Description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<ComboBox x:Name="cmb1" ItemsSource="{Binding CboItemsource}"
SelectedItem="{Binding comboboxSelecteditem, Mode=TwoWay}"
Style="{StaticResource cmbStyle}" />
<ComboBox x:Name="cmb2" ItemsSource="{Binding OtherItemsource}"
SelectedItem="{Binding OtherSelecteditem, Mode=TwoWay}"
Style="{StaticResource cmbStyle}" />
</StackPanel>
</Window>
I am working with a Wpf/XAML based application which has DataGrid with one of the DataGridColumn containing the TreeView control to let user select the item required.
<DataGrid.Columns>
<DataGridTextColumn Header="SerialNumber" Width="*" Binding="{Binding SerialNumber}" />
<DataGridTemplateColumn Header="Field" Width="*">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<uControls:FieldTreeViewControl />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CurrentField.FieldName,Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Field column in above code is the one which displays treeviewcontrol in the DataGrid cell by referencing the FieldTreeViewControl and it works perfectly. The xaml code of FieldTreeViewControl is :
<UserControl>
.......
<Grid>
<TreeView x:Name="MyUITreeView" ItemsSource="{Binding Fields}">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsNodeExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsNodeSelected, Mode=TwoWay}" />
</Style>
<DataTemplate x:Key="NormalTemplate">
<StackPanel Orientation="Horizontal">
<!--<TextBlock Text="-" Margin="3"/>-->
<TextBlock Text="{Binding FieldName}" Margin="3"/>
<StackPanel.ContextMenu>
<ContextMenu Name="myChildMenu" DataContext="{Binding PlacementTarget,RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Field" Command="{Binding DataContext.AddFieldCommand}" CommandParameter="{Binding}">
</MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</DataTemplate>
<!--<DataTemplate x:Key="EditTemplate">
<TextBox Text="{Binding FieldName}"/>
</DataTemplate>-->
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<ContentPresenter Content="{Binding}">
<ContentPresenter.Style>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="ContentTemplate" Value="{StaticResource NormalTemplate}"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding IsNodeSelected,
RelativeSource={RelativeSource
FindAncestor,
AncestorType={x:Type TreeViewItem}}}"
Value="True">
</DataTrigger>
</Style.Triggers>
</Style>
</ContentPresenter.Style>
</ContentPresenter>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
Now when user completes selecting an item from treeview I want to collapse treeview to show only that selected item. Later when user wants to change his selection , then the treeview should be available again by clicking on that column/cell. Is that possible to do this in wpf/XAML ? I tried to follow the link but not able to implement it for my scenario.
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>
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.
I have the following tree view template :
<TreeView x:Name="counterTree" ItemsSource="{Binding CounterCheckBoxList}" x:FieldModifier="private">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Name="counterTreePanel">
<CheckBox Background="LightBlue"
IsChecked="{Binding IsChecked}" Checked="CounterTreeCheckBoxChecked" Unchecked="CounterTreeCheckBoxUnchecked"
VerticalAlignment="Center" Tag="{Binding Id}" />
<Label Content="{Binding Name }"
Tag="{Binding ParentId}"
Name="counterLabel"
Padding="1,1,1,1" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="False" />
<Setter Property="KeyboardNavigation.AcceptsReturn" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
The ItemsSource of the TreeView is List<CounterCheckBox>.
CounterCheckBox class has a property as : public List Children.
My requirement was that if this list is empty the 'CheckBox' should not be visible and it there are Children the Checkbox should be visible.How do I bind the count of the list to the Visiblity property of the Checkbox.
Thanks in advance.
You have to use a IValueConverter.