1

I am trying to dynamically create a Context Menu for a data grid that passes in the selected menu item (Mvvm). I want the DataContext to be the same for the for the context menu as the grid.

I have the following Xaml

<Grid>
  <!-- Cut some other stuff -->
  <Border Grid.Row="2" BorderBrush="Black" BorderThickness="1">
    <DataGrid x:Name="MyDataGrid" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=GridData}" AutoGenerateColumns="False" IsReadOnly="True" GridLinesVisibility="None" SelectionUnit="Cell" SelectionMode="Single">
      <DataGrid.ContextMenu>
        <ContextMenu ItemsSource="{Binding ContextMenuActions}">
          <MenuItem Header="{Binding DisplayName}" Command="{Binding Command}" />
        </ContextMenu>
      </DataGrid.ContextMenu>
      <DataGrid.Columns>
        <DataGridTextColumn  Header="DataOne" Width="130" Binding="{Binding Path=DataOne}"/>
        <DataGridTextColumn  Header="DataTwo"   Width="100" Binding="{Binding Path=DataTwo}"/>
      <DataGrid.Columns>
      <DataGrid.InputBindings>
        <MouseBinding Gesture="RightClick"  Command="{Binding DataGridRightClick}" CommandParameter="{Binding ElementName=MyDataGrid, Path=SelectedCells}" />
      </DataGrid.InputBindings>
    </DataGrid>
  </Border>
</Grid> 

and the following classes for my data context that I use for my datagrid and would also like to use for my context menu (I have cut out all the data grid population code for readability ) and menuitems

public class DataViewModel : ViewModelBase // Implements INotifyPropertyChanged
{
    // All code that populates the grid has been removed

    public ObservableCollection<MenuItemViewModel> ContextMenuActions { get; set; }
    public ICommand DataGridRightClick { get; private set; }

    public MarketDataViewModel()
    {
        DataGridRightClick = new RelayCommand(RightClick);
    }

    public void RightClick(object obj)
    {
        MenuItemViewModel menuItem = new MenuItemViewModel("Test", new RelayCommand(TestCall));
        ContextMenuActions.Add(menuItem); // I ensure this is added on the gui thread
        MenuItemViewModel menuItem1 = new MenuItemViewModel("Test2", new RelayCommand(TestCall));
        ContextMenuActions.Add(menuItem1); // I ensure this is added on the gui thread but for 
    }

    private void TestCall(object obj)
    {
        // want to pass in the selected menuitem
    }
}

public class MenuItemViewModel 
{
    public MenuItemViewModel(string displayName,ICommand command)
    {
        DisplayName = displayName;
        Command = command;
    }

    public string DisplayName { get; set; }
    public ICommand Command { get; set; }
}

Currently when I click on the datagrid the right click event gets called and runs fine but an empty context menu appears on the grid.

Thanks, Nick

5
  • You're setting the ContextMenu items twice, by the way. That MenuItem you have in your XAML is probably preventing the ItemsSource binding to work, since you can only use one approach: the Items collection (that you're setting on XAML) or ItemsSource. Commented Jul 27, 2015 at 14:32
  • Were you trying to set the ItemTemplate, maybe? Commented Jul 27, 2015 at 14:33
  • yes, I did try setting the item template but that didn't help. How exactly would I do that. I think I did something like <ContextMenu ItemsSource="{Binding ContextMenuActions}"> <MenuItem Header="{Binding DisplayName}" Command="{Binding Command}" /> Commented Jul 27, 2015 at 15:02
  • pressed enter by accident <ContextMenu ItemsSource="{Binding ContextMenuActions}"><ItemTemplate><DataTemplate DataType="MenuItem"> <MenuItem Header="{Binding DisplayName}" Command="{Binding Command}" /> ...closing tags. Is this correct? Commented Jul 27, 2015 at 15:03
  • 1
    Yep, that's correct. Try doing that and also doing what @MikeEason said in his answer. I think it may be a combination of both things what you need. Commented Jul 27, 2015 at 15:13

1 Answer 1

1

You need to bind to the DataContext.ContextMenuActions of the parent DataGrid. The easiest way to achieve this is by using the following binding:

<ContextMenu ItemsSource="{Binding DataContext.ContextMenuActions, ElementName=MyDataGrid}" ... 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, but now I get System.Windows.Data Warning: 74 : Lookup name MyDataGrid: queried ContextMenu (hash=13257961) System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=MyDataGrid'. BindingExpression:Path=DataContext.ContextMenuActions; DataItem=null; target element is 'ContextMenu' (Name=''); target property is 'ItemsSource' (type 'IEnumerable'). I tried adding x:Reference which was suggested in other posts but that didn't work either. Any ideas why this might be?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.