Dynamic Treeview Binding with XML file-XBAP Application - wpf

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>

Related

Element Binding To TreeView SelectedItem Where TreeViewItem has ItemsSource

I have the following UserControl:
<UserControl x:Class="ConcreteAnalyzer.Views.CenterSectionPropertiesView"
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:c="clr-namespace:ConcreteAnalyzer.Converters"
xmlns:local="clr-namespace:ConcreteAnalyzer.Views"
xmlns:vm="clr-namespace:ConcreteAnalyzer.ViewModels.CenterSection"
mc:Ignorable="d">
<UserControl.Resources >
<c:DebugConverter x:Key="DebugConverter"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="8"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<TreeView Grid.Row="0" x:Name="CenterSectionTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:PanViewModel}">
<TreeViewItem Header="Pan"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
<TreeViewItem Header="Center Section" DataContext="{Binding CenterSection}">
<TreeViewItem Header="Front" DataContext="{Binding XPositive}" ItemsSource="{Binding Pans, Converter={StaticResource DebugConverter}}"/>
<TreeViewItem Header="Back" DataContext="{Binding XNegative}" ItemsSource="{Binding Pans}"/>
<TreeViewItem Header="Left" DataContext="{Binding YPositive}" ItemsSource="{Binding Pans}"/>
<TreeViewItem Header="Rigth" DataContext="{Binding YNegative}" ItemsSource="{Binding Pans}"/>
</TreeViewItem>
</TreeView>
<GridSplitter Grid.Row="1" Height="8" ResizeDirection="Rows" HorizontalAlignment="Stretch" ResizeBehavior="PreviousAndNext">
<GridSplitter.Template>
<ControlTemplate TargetType="{x:Type GridSplitter}">
<Grid>
<Button Content="⁞" Background="Transparent" Foreground="White"/>
<Rectangle Fill="{StaticResource TurqoiseBrush}"/>
</Grid>
</ControlTemplate>
</GridSplitter.Template>
</GridSplitter >
<ContentControl Content="{Binding SelectedItem.DataContext, ElementName=CenterSectionTree, Converter={StaticResource DebugConverter}}" Grid.Row="2">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type vm:CenterSectionViewModel}">
<TextBlock Text="Center Section"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:WallViewModel}">
<TextBlock Text="Wall"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:PanViewModel}">
<TextBlock Text="Pan"/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Grid>
This works just fine for the Treeview items that are hard-coded but if I select one of the pans, the ElementBinding does not connect. I could change the treeview to use HiearchicalDataTemplate, but to do that I think I have to create dummy collections to bind to at each level as well as add a property to the walls so that I can tell which wall is which. Creating all that dummy info just to make the treeview work has some code smell to me.
Any thoughts on the best way to get this to work?
edit:
The reason it's not working is because when the hard-coded treeview items are selected the databinding points at the TreeViewItem itself and so I was binding to the SelectedItem.DataContext. When you select a Pan, the SelectedItem is the PanViewModel, not the TreeViewItem.
If I Try simply binding to the SelectedItem, the hard-coded TreeViewItems will not work because it tries to inject the TreeViewItem itself into a ContentControl, which throws an exception.
Binding to the SelectedItem.DataContext won't work because the PanViewModel doesn't have a DataContext. I'm still not seeing an elegant solution to this.

Tree View IsSelected with hierarchical data template

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>

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>

Overriding Style of WPF TreeView Items

I am using the awesome MahAppsMetro WPF control suite. I have a tree view that loads the file system. I also want to display images in the TreeViewItems so I have overridden the metro tree style as follows
<UserControl x:Class="GDE.Tree.TreeView"
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:Caliburn="http://www.caliburnproject.org"
xmlns:Metro="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<UserControl.Resources>
<HierarchicalDataTemplate x:Key="TreeTemplate" ItemsSource="{Binding Path=Children}"/>
</UserControl.Resources>
<!--TreeView-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0"
Margin="5"
IsReadOnly="True"
Text="{Binding SelectedPath, Mode=TwoWay}"/>
<TreeView Grid.Row="1"
Margin="5"
ItemsSource="{Binding RootChildren}"
ItemTemplate="{StaticResource TreeTemplate}">
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}"
BasedOn="{StaticResource MetroTreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Name="img"
Width="16"
Height="16"
Stretch="Fill"
Source="{Binding Path=Icon, Mode=OneTime}"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="{Binding DisplayName, Mode=OneTime}"
Margin="5,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.Resources>
</TreeView>
</Grid>
</UserControl>
But this does not seem to work as intended and I can't figure out why. From this XAML, I get no binding errors and the visuals look like:
I have gone more extensive with the XAML mark up but I am getting the exact same visuals. How can I change the above XAML to give me the Image/TextBlocks as well as the MahApps look and feel?
Thanks for your time.
To sum up comments instead of changing Style you need to move StackPanel from DataTemplate directly into HierarchicalDataTemplate as at the moment used template has no content:
<HierarchicalDataTemplate x:Key="TreeTemplate" ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal">
<Image Name="img" ... />
<TextBlock Text="{Binding DisplayName, Mode=OneTime}" ... />
</StackPanel>
</HierarchicalDataTemplate>

ListView with ScrollViewer but no MouseWheelEvents

I have the following List:
These are ListView with Expanders as ListViewItems. The ListView itself is in a ScrollViewer to make the right scrolling behaviour.
My Problem is that the MouseWheel is not working on this List.
Here is the XAML:
<Window x:Class="ResourceListExpanderStyle.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:ResourceListExpanderStyle.Converter"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<converter:DeviceTypeGroupToDeviceListConverter x:Key="DeviceTypeGroupToDeviceListConverter" />
<converter:IntegerToBrushConverter x:Key="IntegerToBrushConverter" />
</Window.Resources>
<DockPanel>
<ScrollViewer x:Name="ScrollViewer">
<ListView x:Name="OuterListView" ItemsSource="{Binding DeviceTypeGroupListByStation}" HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Path=NAME}" Background="{Binding Path=BACKCOLOR, Converter={StaticResource IntegerToBrushConverter}}">
<ListView x:Name="InnerListView" ItemsSource="{Binding Converter={StaticResource DeviceTypeGroupToDeviceListConverter}}" HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=NAME}" Background="{Binding Path=BACKCOLOR, Converter={StaticResource IntegerToBrushConverter}}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Expander>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
</DockPanel>
Any Idea?

Resources