Tree View IsSelected with hierarchical data template - wpf

I have found a couple examples of binding an IsSelected Property in the view model. However none of these deal with a TreeView with Hierachical data templates.
My Hierachy is like this
VM_Part
VM_Step
VM_Step
VM_Step
VM_Part
VM_Step
VM_Step
I would like to be able to select multiple VM_Part instances or Multiple VM_Steps under one part. The idea being I can have a context menu and perform various commands on the selected items
<Window x:Class="NameSpace1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Hipot_Sequence_Editor"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
Title="MainWindow" Height="677.538" Width="896.456">
<Window.DataContext>
<local:VM_Main></local:VM_Main>
</Window.DataContext>
<Grid>
<TreeView x:Name="treeView" Grid.Column="1" HorizontalAlignment="Left" Height="628" Margin="10.2,10,0,0" VerticalAlignment="Top" Width="237" Grid.RowSpan="2" ItemsSource="{Binding Parts}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type viewModels:VM_Part}" ItemsSource="{Binding VM_Steps}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SequenceNumber}" />
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding PartNumber}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type viewModels:VM_Step}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
This seems to me the closet example to what I need. I tried the first answered suggested
<TreeView.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected"
Value="{Binding Path=IsSelected, Mode=TwoWay}" />
</Style>
</TreeView.Resources>
However it seems that this code assumes IsSelected is in VM_Main and not in VM_Part or VM_Step

each TreeViewItem in a hierarchy
VM_Part TreeViewItem
VM_Step TreeViewItem
VM_Step TreeViewItem
VM_Step TreeViewItem
has its own DataContext (VM_Part or VM_Step)
so if VM_Part and VM_Step have IsSelected property, then style for TreeViewItem is defined correctly
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected"
Value="{Binding Path=IsSelected, Mode=TwoWay}" />
</Style>
however, multiselection in TreeView is probably simpler with CheckBoxes added to item template and bound to view model IsSelected property:
<HierarchicalDataTemplate DataType="{x:Type viewModels:VM_Part}" ItemsSource="{Binding VM_Steps}">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding SequenceNumber}" />
<TextBlock Text=" - "/>
<TextBlock Text="{Binding PartNumber}" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type viewModels:VM_Step}">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>

Related

WPF DataTemplate and binding with TextBlock

<Window.Resources>
<DataTemplate x:Key="pointGroupTemplate" DataType="{x:Type ac:PointGroup}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
<DataTemplate x:Key="tt2" DataType="{x:Type ac:PointGroup}">
<TextBlock Text="{Binding PointsCount}"/>
</DataTemplate>
</Window.Resources>
the first template works well with:
<ComboBox x:Name="comboBox1" ItemTemplate="{StaticResource pointGroupTemplate}" SelectionChanged="ComboBox1_SelectionChanged"
Height="25" Margin="0,5,0,5">
but i want to use the second one in a textblock
<TextBlock x:Name="textBlock1" Text="{Binding ElementName=comboBox1 ,Path=SelectedItem ?????}"/>
anyhelp.
In order to have a DataTemplate applied, you need a ContentPresenter or ContentControl:
<ContentControl ContentTemplate="{StaticResource tt2}"
Content="{Binding SelectedItem, ElementName=comboBox1}"/>

View Controls show/hide WPF MVVM

I have a View (in MVVM) which have some controls including a treeview. A ViewModel which is the datacontext and a Model, everything is working fine till now. **I have two cases:
**
I want my View to show a ContextMenu against Treeview items.
The other case, it should not show a ContextMenu against the Treeview items
Is this possible with one View or there should be two different Views for this purpose, for my personal work it would be better if I have one View.
The VM and model are very simple just having the binded properties of the View.
View.xaml
<UserControl x:Class="SPM.SystemExplorer.View.SystemExplorerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SPM.SystemExplorer.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
xmlns:viewModel="clr-namespace:SPM.SystemExplorer.ViewModel"
xmlns:classes="clr-namespace:SPM.SystemExplorer.Classes">
<UserControl.DataContext>
<viewModel:SystemExplorerViewVM></viewModel:SystemExplorerViewVM>
</UserControl.DataContext>
<Grid>
<StackPanel>
<Label Content="{Binding Test}"></Label>
<TreeView Grid.Row="1" ItemsSource="{Binding SystemProjects}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type classes:SystemProject}" ItemsSource="{Binding ParticipantProjects}">
<StackPanel Orientation="Horizontal">
<TreeViewItem Header="{Binding NameOfSystemProject}"></TreeViewItem>
<TreeViewItem Header="{Binding AuthorOfSystemProject}"></TreeViewItem>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type classes:ParticipantProject}">
<StackPanel Orientation="Horizontal">
<TreeViewItem Header="{Binding NameOfParticipantProject}"></TreeViewItem>
<TreeViewItem Header="{Binding AuthorOfParticipantProject}"></TreeViewItem>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</StackPanel>
</Grid>
You could add a property (ShowContextMenu) to your SystemExplorerViewVM class that you set to true/false depending on whether you want to display the ContextMenu. You could then use a Style with a DataTrigger in your XAML:
<TreeView Grid.Row="1" ItemsSource="{Binding SystemProjects}">
<TreeView.Resources>
<ContextMenu x:Key="cm">
<MenuItem Header="1" />
<MenuItem Header="2" />
</ContextMenu>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding DataContext.ShowContextMenu, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="True">
<Setter Property="ContextMenu" Value="{StaticResource cm}" />
</DataTrigger>
</Style.Triggers>
</Style>
<HierarchicalDataTemplate DataType="{x:Type classes:SystemProject}" ItemsSource="{Binding ParticipantProjects}">
<StackPanel Orientation="Horizontal">
<TreeViewItem Header="{Binding NameOfSystemProject}"></TreeViewItem>
<TreeViewItem Header="{Binding AuthorOfSystemProject}"></TreeViewItem>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type classes:ParticipantProject}">
<StackPanel Orientation="Horizontal">
<TreeViewItem Header="{Binding NameOfParticipantProject}"></TreeViewItem>
<TreeViewItem Header="{Binding AuthorOfParticipantProject}"></TreeViewItem>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView>

Switch datatemplate depending on a selected string value in combobox

Based on a selected string value in the combobox I want to either show red/blue datatempalte inside the grid.
Can this be done without a ContentControl?
<UserControl.Resources >
<DataTemplate x:Key="red">
<TextBox Text="red" />
</DataTemplate>
<DataTemplate x:Key="blue">
<TextBox Text="blue" />
</DataTemplate>
</UserControl.Resources>
<ComboBox ??? />
<Grid>
// Show red or blue datatemplate here
</Grid>
Why not use a ContentControl?
To make this work simply i would put the templates in an array, which the ComboBox then can bind to:
<x:Array x:Key="templates" Type="{x:Type DataTemplate}">
<DataTemplate>
<DataTemplate.Resources>
<sys:String x:Key="DisplayString">Red</sys:String>
</DataTemplate.Resources>
<TextBox Text="red" />
</DataTemplate>
<DataTemplate>
<DataTemplate.Resources>
<sys:String x:Key="DisplayString">Blue</sys:String>
</DataTemplate.Resources>
<TextBox Text="blue" />
</DataTemplate>
</x:Array>
<ComboBox Name="combo" ItemsSource="{StaticResource templates}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Resources[DisplayString]}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Grid>
<ContentControl ContentTemplate="{Binding SelectedItem, ElementName=combo}" />
</Grid>

Dynamic Treeview Binding with XML file-XBAP Application

I have a XML file which has maximum three levels of child elements so i need to bind the file with TreeView in WPF for XBAP App Dynamically.
Do we need to use Hierarchical template or is there any other way to get easy binding..
for example:
<TriggerList>
<Trigger>
<TriggerName>trig1</TriggerName>
<TriggerSource>manual</TriggerSource>
<TriggerInfo>
<Alaramid>2312</Alaramid>
<Area>area1</Area>
<ToolType>OLF121</ToolType>
</TriggerInfo>
</Trigger>
</TriggerList>
I want to make this in tree view through Dynamic Binding ..
Answer is :
<UserControl x:Class="XTREAMSUI.UserControls.ExecutionList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mvvm="clr-namespace:MvvmFoundation.Wpf;assembly=MvvmFoundation.Wpf"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="230">
<UserControl.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding RFCNameList}" x:Key="RFCTemplate">
<TextBlock Text="{Binding RFCName}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding RFCNameList}" x:Key="TriggerIDTemplate" ItemTemplate="{StaticResource RFCTemplate}">
<TextBlock Text="{Binding TriggerID}" IsEnabled="False"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding TriggerIDList}" x:Key="TriggerSourceTemplate" ItemTemplate="{StaticResource TriggerIDTemplate}">
<TextBlock Text="{Binding TriggerSource}" IsEnabled="False"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding TriggerList}" x:Key="TriggerTemplate" ItemTemplate="{StaticResource TriggerSourceTemplate}">
<TextBlock Text="{Binding HostMachineName}" IsEnabled="False"/>
</HierarchicalDataTemplate>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</UserControl.Resources>
<Grid Name="gridExecutionlst" IsEnabled="{Binding IsExecutionListEnabled, Mode=TwoWay}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--<TreeView Grid.Row="0" Name="treeviewExecutionList" Height="400" Width="200" ItemsSource="{Binding TriggerListXML}" ItemTemplate="{StaticResource dataTemplateExecutionList}"></TreeView>-->
<TreeView Name="treeviewExecutionList" Height="450" Width="230" FontWeight="Normal" ItemsSource="{Binding Path=TriggerList,Mode=TwoWay}" ItemTemplate="{StaticResource TriggerTemplate}">
<mvvm:CommandBehaviorCollection.Behaviors>
<mvvm:BehaviorBinding Command="{Binding ListBoxCommand}" Event="MouseDoubleClick" CommandParameter="{Binding ElementName=treeviewExecutionList, Path=SelectedItem}"/>
</mvvm:CommandBehaviorCollection.Behaviors>
</TreeView>
</Grid>
</UserControl>
Answer is :
`
<HierarchicalDataTemplate ItemsSource="{Binding RFCNameList}" x:Key="RFCTemplate">
<TextBlock Text="{Binding RFCName}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding RFCNameList}" x:Key="TriggerIDTemplate" ItemTemplate="{StaticResource RFCTemplate}">
<TextBlock Text="{Binding TriggerID}" IsEnabled="False"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding TriggerIDList}" x:Key="TriggerSourceTemplate" ItemTemplate="{StaticResource TriggerIDTemplate}">
<TextBlock Text="{Binding TriggerSource}" IsEnabled="False"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding TriggerList}" x:Key="TriggerTemplate" ItemTemplate="{StaticResource TriggerSourceTemplate}">
<TextBlock Text="{Binding HostMachineName}" IsEnabled="False"/>
</HierarchicalDataTemplate>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
<TreeView Name="treeviewExecutionList" Height="450" Width="230" FontWeight="Normal" ItemsSource="{Binding Path=TriggerList,Mode=TwoWay}" ItemTemplate="{StaticResource TriggerTemplate}">
<mvvm:CommandBehaviorCollection.Behaviors>
<mvvm:BehaviorBinding Command="{Binding ListBoxCommand}" Event="MouseDoubleClick" CommandParameter="{Binding ElementName=treeviewExecutionList, Path=SelectedItem}"/>
</mvvm:CommandBehaviorCollection.Behaviors>
</TreeView>

Add an event on ListBoxItems build with ItemTemplate

I have a ListBox like this :
<ListBox DataContext="{Binding UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}"
ListBoxItem.Selected="ListBoxItem_Selected">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<DockPanel>
<Label Content="{Binding Path=Attribute[rdv].Value, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<DockPanel>
<Label Content="{Binding Path=Attribute[type].Value, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{Binding Path=Element[ville].Attribute[saisie].Value, UpdateSourceTrigger=PropertyChanged}" />
<Label Content=":" />
<Label Content="{Binding Path=Element[adresse].Attribute[saisie].Value, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
<Separator />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I whant to rise an event when an ListeBoxItem is selected.
As you can see, I've tried with ListBoxItem.Selected="ListBoxItem_Selected" but it does not work.
Do you have an idea ?
Tanks by advance !
You handler doesn't get called because the Selected event is already handled by the ListBox. You should handle the SelectionChanged event in the ListBox instead:
<ListBox DataContext="{Binding UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}"
SelectionChanged="ListBox_SelectionChanged">
Alternatively, you can use an ItemContainerStyle to attach the handler to every ListBoxItem:
<ListBox DataContext="{Binding UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="Selected" Handler="ListBoxItem_Selected"/>
</Style>
</ListBox.ItemContainerStyle>

Resources