In WPF, with MVVM light, there's a Class
(which is consist of some students), and the Class
hold some Student
s.
Right-Click one Student's name, then will show a MessageBox
, it is ok in this way:
ClassDetailView.xaml
<UserControl DataContext="{Binding ClassDetail, Source={StaticResource Locator}}">
<DockPanel>
<ListBox
ItemsSource="{Binding Students}"
DisplayMemberPath="Name">
<ListBox.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
<MenuItem
Header="Show Selected"
Command="{Binding Path=DataContext.RemoveStudentCommand}"
CommandParameter="{Binding Path=SelectedItem}"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</DockPanel>
</UserControl>
But, it don't work in this way (use ListBox.ItemContainerStyle):
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Show Selected"
Command="{Binding Path=DataContext.RemoveStudentCommand}"
CommandParameter="{Binding Path=SelectedItem}"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
instead of
<ListBox.ContextMenu>
<ContextMenu ...>
...
<ContextMenu />
</ListBox.ContextMenu>
ClassDetailViewModel.cs
namespace ContextMenu.ViewModel
{
public class ClassDetailViewModel : ViewModelBase
{
public ClassDetailViewModel()
{
CreateData();
}
public void CreateData()
{
students.Add(new StudentViewModel() { Name = "QQ" });
students.Add(new StudentViewModel() { Name = "WW" });
students.Add(new StudentViewModel() { Name = "EE" });
students.Add(new StudentViewModel() { Name = "RR" });
students.Add(new StudentViewModel() { Name = "AA" });
students.Add(new StudentViewModel() { Name = "SS" });
students.Add(new StudentViewModel() { Name = "DD" });
students.Add(new StudentViewModel() { Name = "FF" });
students.Add(new StudentViewModel() { Name = "ZZ" });
students.Add(new StudentViewModel() { Name = "XX" });
}
public const string StudentsPropertyName = "Students";
private ObservableCollection<StudentViewModel> students =
new ObservableCollection<StudentViewModel>();
public ObservableCollection<StudentViewModel> Students
{
get { return students; }
set
{
if (students == value) { return; }
students = value;
RaisePropertyChanged(StudentsPropertyName);
}
}
private RelayCommand<StudentViewModel> removeStudentCommand;
public RelayCommand<StudentViewModel> RemoveStudentCommand
{
get
{
return removeStudentCommand
?? (removeStudentCommand =
new RelayCommand<StudentViewModel>(ExecuteRemoveStudentCommand));
}
}
private void ExecuteRemoveStudentCommand(StudentViewModel student)
{
if (null == student) { return; }
MessageBox.Show(string.Format("RemoveStudent:{0}", student.Name));
}
}
}
StudentViewModel.cs
namespace ContextMenu.ViewModel
{
public class StudentViewModel : ViewModelBase
{
public const string NamePropertyName = "Name";
private string name = "";
public string Name
{
get { return name; }
set
{
if (name == value) { return; }
name = value;
RaisePropertyChanged(NamePropertyName);
}
}
}
}
You need a proxy to bind commands to a context menu of a listboxitem. See the answer here:
http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With