Tree View Command not working on context menu

abijith gowda 61 Reputation points
2020-04-24T19:48:45.523+00:00

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 Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,671 questions
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-27T06:42:01.133+00:00

    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
    
    0 comments No comments

0 additional answers

Sort by: Most helpful