question

abijithgowda-5277 avatar image
abijithgowda-5277 asked ·

Tree View Command not working on context menu

I am working on a WPF application. It contains a multi select tree view. The tree is supposed to have different context menu items for each node(i.e at each level of the tree). I am able to populate the tree and even get the context menu to have different options based on the type of data in the tree view. Once i have done this, the command bindings to the context menu items has stopped working. i get an error in the output window as below:

System.Windows.Data Error: 40 : BindingExpression path error: 'RefreshEvent' property not found on 'object' ''RootNameList' (HashCode=49313939)'. BindingExpression:Path=RefreshEvent; DataItem='RootNameList' (HashCode=49313939); target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')

As it is visible in the error, the DataItem is not pointing to the intended ViewModel. Can anyone help me to resolve this issue.

I have attached the code as an attachment.7588-treeview.xml


windows-wpf
treeview.xml (4.9 KiB)
3 comments
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, there aren't ICommand properties GetConfigurationEvent and PutConfigurationEvent in data item. Where you declare this properties?

If you declare this properties in ViewModel you must set Source like this:

   <Window.Resources>
     <local:ViewModel x:Key="vm"/>
   </Window.Resources>
   <Grid DataContext="{StaticResource vm}">
     <TreeView ItemsSource="{Binding TreeViewDataCollection}">
       <TreeView.Resources>
         <ContextMenu x:Key="ChildMenu" >
           <MenuItem Header="Get Configuration" Command="{Binding GetConfigurationEvent, Source={StaticResource vm}}"/>
           <MenuItem Header="Put Configuration" Command="{Binding PutConfigurationEvent, Source={StaticResource vm}}"/>
         </ContextMenu>
       </TreeView.Resources>
1 Vote 1 · ·

Hi Peter, I made changes as you suggested and added the datacontext in the xaml instead of the code behind and it worked out fine.

Thank you for your help!!

0 Votes 0 · ·
AlexLi-MSFT avatar image AlexLi-MSFT abijithgowda-5277 ·

If you resolve the issue, please accept the helpful as answer.

0 Votes 0 · ·

1 Answer

PeterFleischer-3316 avatar image
PeterFleischer-3316 answered ·

Hi, try following demo and accept the helpful as answer:

XAML:

 <Window x:Class="Window012"
         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:WpfApp1.WpfApp012"
         mc:Ignorable="d"
         Title="Window012" Height="450" Width="800">
   <Window.Resources>
     <local:ViewModel x:Key="vm"/>
   </Window.Resources>
   <Grid DataContext="{StaticResource vm}">
     <TreeView ItemsSource="{Binding TreeViewDataCollection}">
       <TreeView.Resources>
         <ContextMenu x:Key="ChildMenu" >
           <MenuItem Header="Get Configuration" 
                     Command="{Binding GetConfigurationEvent, Source={StaticResource vm}}"
                     CommandParameter="{Binding}"/>
           <MenuItem Header="Put Configuration" 
                     Command="{Binding PutConfigurationEvent, Source={StaticResource vm}}"
                     CommandParameter="{Binding}"/>
         </ContextMenu>
       </TreeView.Resources>
       <TreeView.ItemContainerStyle>
         <Style TargetType="{x:Type TreeViewItem}">
           <Setter Property="ContextMenu" Value="{StaticResource ChildMenu}"/>
         </Style>
       </TreeView.ItemContainerStyle>
       <TreeView.ItemTemplate>
         <HierarchicalDataTemplate ItemsSource="{Binding HostGroupName}" DataType="{x:Type local:RootNameList}">
           <Label Content="{Binding RootSubnet}"/>
         </HierarchicalDataTemplate>
       </TreeView.ItemTemplate>
     </TreeView>
   </Grid>
 </Window>

ViewModel:

 Imports System.ComponentModel
    
 Namespace WpfApp012
    
   Public Class ViewModel
    
     Public Sub New()
       For i = 1 To 10
         Dim rnl As New RootNameList With {.RootSubnet = $"RootSubnet{i}"}
         For k = 1 To 10
           rnl.HostGroupName.Add(New RootNameList With {.RootSubnet = $"HostGroupName {k + i * 10}"})
         Next
         col.Add(rnl)
       Next
       cvs.Source = col
     End Sub
    
     Private cvs As New CollectionViewSource
     Private col As New AsyncObservableCollection(Of RootNameList)
     Public ReadOnly Property TreeViewDataCollection As ICollectionView
       Get
         Return cvs.View
       End Get
     End Property
     Public ReadOnly Property GetConfigurationEvent As ICommand
       Get
         Return New RelayCommand(Sub(state)
                                   Debug.WriteLine($"Get: {CType(state, RootNameList).RootSubnet}")
                                 End Sub)
       End Get
     End Property
     Public ReadOnly Property PutConfigurationEvent As ICommand
       Get
         Return New RelayCommand(Sub(state)
                                   Debug.WriteLine($"Put: {CType(state, RootNameList).RootSubnet}")
                                 End Sub)
       End Get
     End Property
    
   End Class
    
   Public Class RootNameList
     Public Property RootSubnet As String
     Public Property HostGroupName As New List(Of RootNameList)
   End Class
    
 End Namespace


Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.