2

I have this View:

<StackPanel>
<StackPanel.DataContext>
    <local:MainViewModel />
</StackPanel.DataContext>
<ListView ItemsSource="{Binding Persons}" x:Name="xamlPersonList">
    <ListBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="EMail" Command="{Binding WriteMailCommand}" CommandParameter="{Binding ElementName=xamlPersonList,Path=SelectedItem}" />
        </ContextMenu>
    </ListBox.ContextMenu>
</ListView>
</StackPanel>

I want to get the selected item (or the clicked item) and do some stuff with it inside my Command-Method. This is my Ctor and Command-Method of my ViewModel:

public ICommand WriteMailCommand { get; private set; }
public MainViewModel()
{
    _persons = new ObservableCollection<Person>();
    for (int i = 0; i < 10; i++)
    {
        _persons.Add(new Person()
        {
            ID = i,
            Name = "Robert " + i
        });
    }

    WriteMailCommand = new RelayCommand<object>(WriteMailMethod);
}

private void WriteMailMethod(object obj)
{
}

The obj parameter is always null. I don't know what I am missing here?! I tried this solution: How to pass listbox selecteditem as command parameter in a button?

Community
  • 1
  • 1
DoubleVoid
  • 777
  • 1
  • 16
  • 46

1 Answers1

4

The binding isn't working because the ContextMenu exists outside of your control's visual tree, and so it's impossible for it to find the ListBox. In fact I'm surprised it's invoking your command without the usual incantation to get the data context of the associated control:

<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" >

Regardless, you can use the answer suggested here, or I can suggest an alternate implementation: add a SelectedPerson property to your view-model:

private Person selectedPerson;
public Person SelectedPerson 
{ 
    get { return selectedPerson; } 
    set
    {
        selectedPerson = value;
        RaisePropertyChanged(); // or whatever your implementation is
    }
}

Your XAML would be simple, too:

<ListView ItemsSource="{Binding Persons}" 
          SelectedItem="{Binding SelectedPerson}">
    <ListBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="EMail" 
                      Command="{Binding WriteMailCommand}" 
                      CommandParameter="{Binding SelectedPerson}" />
        </ContextMenu>
    </ListBox.ContextMenu>
</ListView>
Community
  • 1
  • 1
Patrick Quirk
  • 23,334
  • 2
  • 57
  • 88
  • Wow okay, that works. I hope I understood it correctly. The ListBox is bound to my SelectedPerson and the CommandParameter always just put my SelectedPerson to my Method as parameter, right?! In this case I could just rely on my SelectedPerson property. Thank you very much! :) – DoubleVoid Nov 06 '15 at 09:20
  • @DoubleVoid Yep, exactly. Happy to help. – Patrick Quirk Nov 06 '15 at 13:35
  • Sometimes the SelectedPerson is null, since I am right clicking the list entry to get my context menu. Is there a workaround for this too?! – DoubleVoid Nov 06 '15 at 13:50
  • Never mind, it has nothing to do with the WPF ListView. I am updating my List every 10 seconds, this removes the selection unfortunately <.< Raising a PropertyChange kills my selection. – DoubleVoid Nov 06 '15 at 13:55