/ / ListBox.ContextMenu Obtener elemento seleccionado a través del comando [duplicar] - wpf, mvvm, mvvm-light

ListBox.ContextMenu Obtener elemento seleccionado mediante comando [duplicar] - wpf, mvvm, mvvm-light

Tengo esta vista:

<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>

Quiero obtener el elemento seleccionado (o el elemento seleccionado) y hacer algunas cosas con él dentro de mi Método de comando. Este es mi Ctor y método de comando de mi 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)
{
}

El parámetro obj siempre es nulo. ¡No sé lo que me estoy perdiendo aquí! Probé esta solución: ¿Cómo pasar el elemento de cuadro de lista seleccionado como parámetro de comando en un botón?

Respuestas

3 para la respuesta № 1

El enlace no funciona porque el ContextMenu existe fuera del árbol visual de su controly, por lo tanto, es imposible encontrar el ListBox. De hecho, me sorprende que invoque su comando sin el encantamiento habitual para obtener el contexto de datos del control asociado:

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

Independientemente, puede usar el respuesta sugerida aquí, o puedo sugerir una implementación alternativa: agregue un SelectedPerson propiedad de su modelo de vista:

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

Tu XAML también sería simple:

<ListView ItemsSource="{Binding Persons}"
SelectedItem="{Binding SelectedPerson}">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="EMail"
Command="{Binding WriteMailCommand}"
CommandParameter="{Binding SelectedPerson}" />
</ContextMenu>
</ListBox.ContextMenu>
</ListView>