5556

Databinding a command to Context Menu with an Observable Collection

Question:

I have a Context menu with some options. One of the options is an Observable collection and I am having issues binding my commands in my view model to them. I have seen many different ways to fix this issue, but none have worked because they do not specifically relate to my problem. Here is my code first:

XAML:

<ListView ItemsSource="{Binding ListViewItems}" SelectionMode="Single"> <ListView.ContextMenu> <ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"> <MenuItem Header="Test" Command="{Binding TestCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}" /> <Separator></Separator> <MenuItem Header="Status" ItemsSource="{Binding DataContext.ObservableCollectionList}" DisplayMemberPath="Name" Command="{Binding Path=DataContext.UpdateCommand}" CommandParameter="{Binding Path=SelectedItem}"/> </ContextMenu> </ListView.ContextMenu> //listviewstuff here </ListView>

VM:

public class VM : ViewModelBase { public RelayCommand UpdateCommand { get; private set; } public Action UpdateCommandAction { get; set; } public ObservableCollection<Status> ObservableCollectionList { get; set; } public VM() { this.UpdateCommand = new RelayCommand(new Action(() => this.UpdateCommandAction.DynamicInvoke()))); } }

Code-behind for the XAML view:

public partial class View { public View() { InitializeComponent(); var ViewDataContext = this.DataContext as VM; ViewDataContext .UpdateCommandAction = UpdateStatus; } private void UpdateStatus() { MessageBox.Show("test"); } }

I inserted a break point and it's not even making it to the method call. The debug output is not showing an error for me when I run the program either. What I don't understand is when I add this Command to the regular menu item that is NOT populated by a data bound list, it works fine. I would appreciate a fresh pair of eyes and some insight in to how this works.

Answer1:

You need to bind the command to all the child items, now you bind it on the parent which will ignore it because it has child items (opens sub-menu instead).

To bind it on the children you need the ItemContainerStyle, create a Setter for the Command there. You will need to walk up again, probably this: {Binding DataContext.DataContext.UpdateCommand, RelativeSource={RelativeSource AncestorType=MenuItem}} (not sure about the AncestorLevel, if it does select itself instead of the parent increase it; double DataContext because you bound to DataContext.ObservableCollectionList, assuming that binding to actually work).

Likewise there is no SelectedItem in a menu, you need another Setter for CommandParameter, it will simply bind to the current item, i.e. {Binding}.

<hr />

<strong>Edit:</strong> Code example:

<MenuItem Header="Status" ItemsSource="{Binding DataContext.ObservableCollectionList}" DisplayMemberPath="Name"> <MenuItem.ItemContainerStyle> <Style TargetType="MenuItem"> <Setter Property="Command" Value="{Binding DataContext.DataContext.UpdateCommand, RelativeSource={RelativeSource AncestorType=MenuItem}}"/> <Setter Property="CommandParameter" Value="{Binding}"/> </Style> </MenuItem.ItemContainerStyle> </MenuItem>

Answer2:

You'll need a List<MenuItem> MenuItems to bind with ContextMenu ItemSource property as

public class MenuItem { public string Header { get; set; } public ICommand Command { get; set; } }

<strong>XAML:</strong> and set itemContainerstyle

<ContextMenu ItemsSource="{Binding MenuItems}" > <ContextMenu.ItemContainerStyle> <Style TargetType="{x:Type MenuItem}" > <Setter Property="Header" Value="{Binding Header}"/> <Setter Property="Command" Value="{Binding Command}" /> </Style> </ContextMenu.ItemContainerStyle> </ContextMenu>

And add as many contextmenu item you want in your ViewModel AS YOU WANT.

Recommend

  • How to use RelativeSource Binding to create DataGrid binding to Model and ViewModel?
  • How to add ComboBox column in XCeed DataGridControl (WPF)
  • Design Time null reference error
  • Xceed datagrid showing combobox
  • No drop with basic gongsolution sample
  • Bind Combobox with huge data in WPF
  • writing to sdcard
  • Getting the new line character without System.getProperty(“line.separator”)?
  • Java - How to convert this string to date?
  • Add vertical separator and labels to R barplot
  • use grep and awk to transfer data from .srt to .csv/xls
  • Gruntfile.js - Throwing error 'Recursive process.nextTick detected\"
  • CUDA Debugging - VS on windows workstation, GPUs on Linux server?
  • WPF Listbox commands
  • Getting zero results in search using elastic4s
  • RPMs for IDAS IoTAgents GE, from Fiware
  • How do I get the list of bad records that didn't load in Bigquery?
  • SQL Query - Table Joining Problems
  • Can't remove headers after they are sent
  • How to use JavaScript to determine whether a file exists in a directory?
  • Sort List of Strings By Version
  • Problems compiling files using JOGL
  • Parsing a CSV string while ignoring commas inside the individual columns
  • Swing - Get new component under mouseReleased
  • MVC3 Razor - ListBox pre-select not working
  • How do I pass the string value parameter of the selected list item from an auto-populated dropdown l
  • Set the selected item in dropdownlist in MVC3
  • ilmerge with a PFX file
  • Spring Data JPA custom method causing PropertyReferenceException
  • Pass value from viewmodel to script in zk
  • Can I display google adwords (AdView) in javafx on android
  • Validaiting emails with Net.Mail MailAddress
  • sending/ receiving email in Java
  • Can I have the cursor start on a particular column by default in jqgrid's edit mode?
  • Cannot Parse HTML Data Using Android / JSOUP
  • Error creating VM instance in Google Compute Engine
  • JTable with a ScrollPane misbehaving
  • unknown Exception android
  • failed to connect to specific WiFi in android programmatically
  • How can I use threading to 'tick' a timer to be accessed by other threads?