Question

I am having some trouble with the following code:

 <TreeViewItem Header="Tests" ItemsSource="{Binding Tests}"  ContextMenu="{StaticResource FolderContext}" >
            <TreeViewItem.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="ContextMenu" Value="{StaticResource SolutionContext}"/>
                </Style>
            </TreeViewItem.ItemContainerStyle>
        </TreeViewItem>

The above TreeViewItem.ItemContainerStyle define a context menu that uses a static resource. the resource xaml is:

 <TreeView.Resources>
            <DataTemplate DataType="{x:Type viewModel:TestViewModel}">
                <Label Content="{Binding Id}"/>
            </DataTemplate>
            <ContextMenu x:Key ="SolutionContext"  StaysOpen="true">
                <MenuItem Header="Remove" Command="{Binding RemoveTest}"/>
                <MenuItem Header="Run" Command="{Binding RunTest}"/>
            </ContextMenu>
            <ContextMenu x:Key="FolderContext"  StaysOpen="true">
                <MenuItem Header="Add..." Command="{Binding AddTest}" />
            </ContextMenu>
        </TreeView.Resources>

The FolderContext resource is working perfectly. The SolutionContext I displaying corectly but...

The Problem:

The SolutionContext commands are not firing.

Here is the all treeview xaml:

    <TreeView Name="TestsTreeView" SelectedItemChanged="TestsTreeView_OnSelectedItemChanged">
        <TreeView.Resources>
            <DataTemplate DataType="{x:Type viewModel:TestViewModel}">
                <Label Content="{Binding Id}"/>
            </DataTemplate>
            <ContextMenu x:Key ="SolutionContext"  StaysOpen="true">
                <MenuItem Header="Remove" Command="{Binding RemoveTest}"/>
                <MenuItem Header="Run" Command="{Binding RunTest}"/>
            </ContextMenu>
            <ContextMenu x:Key="FolderContext"  StaysOpen="true">
                <MenuItem Header="Add..." Command="{Binding AddTest}" />
            </ContextMenu>
        </TreeView.Resources>
        <TreeViewItem Header="Tests" ItemsSource="{Binding Tests}"  ContextMenu="{StaticResource FolderContext}" >
            <TreeViewItem.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="ContextMenu" Value="{StaticResource SolutionContext}"/>
                </Style>
            </TreeViewItem.ItemContainerStyle>
        </TreeViewItem>
    </TreeView>

How can I make the commands fire?

I tried specifying the the command path in the data context(viewmodel) explicitly, didn't work.

The following link is a sample project with the basic code to demonstrate the problem

https://www.sugarsync.com/pf/D6837746_80955217_310316

Any help would be appreciated.

Was it helpful?

Solution

According to the attached source you have all 3 commands as part of MainViewModel

public class MainViewModel : ViewModelBase
{
    public RelayCommand RemoveTest { get; set; }
    public RelayCommand RunTest { get; set; }
    public RelayCommand AddTest { get; set; }

    ...
}

but you need to to remember that each child item will have different DataContext then the whole TreeView. Because you bind ItemsSource to List<Test> this means that DataContext for each child TreeViewItem will be set to different instance of Test object and this class does not contain RemoveTest nor RunTest commands. Now you have 2 choices:

  1. move RemoveTest and RunTest commands to Test class
  2. change binding source for these 2 commands so it points to MainViewModel
<ContextMenu x:Key ="SolutionContext" StaysOpen="true">
   <MenuItem Header="Remove" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=DataContext.RemoveTest}"/>
   <MenuItem Header="Run" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=DataContext.RunTest}"/>
</ContextMenu>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top