My command is inside my ViewModel. I need to pass the DataGrid where my Menuitem is nested. How is this possible ?
<MenuItem Header="Delete item/s" Command="{Binding RemoveHistoryItem}" CommandParameter="{Binding ElementName=HistoryDataGrid}">
You should definitely not send the UIElement back to your ViewModel (like Jeffery stated). Try to bind the DataGrid properties you need to the ViewModel, then access them inside the command handler.
I used a button for illustration, but this will work for your MenuItem in the same way.
ViewModel:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public ICommand RemoveHistoryItemCommand { get; private set; }
private HistoryItem _selectedHistoryItem;
public HistoryItem SelectedHistoryItem { get { return _selectedHistoryItem; } set { _selectedHistoryItem = value; OnPropertyChanged("SelectedHistoryItem"); } }
private ObservableCollection<HistoryItem> _historyItems = new ObservableCollection<HistoryItem>();
public ObservableCollection<HistoryItem> HistoryItems { get { return _historyItems; } set { _historyItems = value; OnPropertyChanged("HistoryItems"); } }
public ViewModel()
{
this.RemoveHistoryItemCommand = new ActionCommand(RemoveHistoryItem);
this.HistoryItems.Add(new HistoryItem() { Year = "1618", Description = "Start of war" });
this.HistoryItems.Add(new HistoryItem() { Year = "1648", Description = "End of war" });
}
// command handler
private void RemoveHistoryItem()
{
if (this.HistoryItems != null)
{
HistoryItems.Remove(this.SelectedHistoryItem);
}
}
}
public class HistoryItem
{
public string Year { get; set; }
public string Description { get; set; }
}
public class ActionCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public Action _action;
public ActionCommand(Action action)
{
_action = action;
}
public bool CanExecute(object parameter) { return true; }
public void Execute(object parameter)
{
if (CanExecute(parameter))
_action();
}
}
Xaml:
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<StackPanel>
<DataGrid ItemsSource="{Binding HistoryItems}" SelectedItem="{Binding SelectedHistoryItem, Mode=TwoWay}" />
<Button Content="Remove selected item" Command="{Binding RemoveHistoryItemCommand}" HorizontalAlignment="Left" />
</StackPanel>
view model to back both controls (or are part of the same 'large' view model), then communicate things behind the scenes. If you do need to send some gui element - use what [Binding ElementName= Path=DataContext.Property...] as @failedprogramming mentioned.
HistoryItemin the CommandParameter.