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?

1
  • is your command WriteMailMethod being hit? ie its hit but with a null parameter Commented Nov 5, 2015 at 16:01

1 Answer 1

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>
Sign up to request clarification or add additional context in comments.

4 Comments

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 Yep, exactly. Happy to help.
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?!
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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.