Command bind to ContextMenu (which on ListBoxItem in ListBox) don't work
本问题已经有最佳答案,请猛点这里访问。
在WPF中,使用MVVM指示灯,有一个
右键单击一个学生的名字,然后显示
ClassDetailView.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <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> |
但是,它不能以这种方式工作(使用ListBox.ItemContainerStyle):
1 2 3 4 5 6 7 8 9 10 11 12 13 | <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> |
代替
1 2 3 4 5 | <ListBox.ContextMenu> <ContextMenu ...> ... <ContextMenu /> </ListBox.ContextMenu> |
ClassDetailViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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); } } } } |
您需要一个代理将命令绑定到listboxitem的上下文菜单。 看到答案:
[WPF] How to bind to data when the DataContext is not inherited
你可以使用contextmenu作为资源吗?
就像是:
1 2 3 4 5 6 7 8 | <UserControl.Resources> <ContextMenu x:name="contextMenuExample" DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"> <MenuItem Header="Show Selected" Command="{Binding Path=DataContext.RemoveStudentCommand}" CommandParameter="{Binding Path=SelectedItem}"/> </ContextMenu> </UserControl.Resources> |
然后在列表上,执行以下操作:
1 | <Listbox ContextMenu = {StaticResource contextMenuExample} ... /> |
或者你真的想使用ItemContainerStyle吗?
from - >如何右键单击列表框中的项目并打开WPF上的菜单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <ListBox Name="someListBox" MouseDown="someListBox_MouseDown"> <ListBox.Resources> <!--Defines a context menu--> <ContextMenu x:Key="MyElementMenu"> <MenuItem Header="Delete" Click="MenuItemDelete_Click"/> </ContextMenu> <!--Sets a context menu for each ListBoxItem in the current ListBox--> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="ContextMenu" Value="{StaticResource MyElementMenu}"/> </Style> </ListBox.Resources> <ListBoxItem>...</ListBoxItem> <ListBoxItem>...</ListBoxItem> <ListBoxItem>...</ListBoxItem> </ListBox> |
通过将ContextMenu移动到ListBoxItem,您已将DataContext从ClassDetailsViewModel(ListBox的DataContext)更改为StudentViewModel(ListBoxItem的DataContext)。 因此,您需要更改路径以访问父ListBox的DataContext以访问RelayCommand。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=DataContext}"> <MenuItem Header="Show Selected" Command="{Binding Path=RemoveStudentCommand}" CommandParameter="{Binding Path=SelectedItem}"/> </ContextMenu> </Setter.Value> </Setter> </Style> </ListBox.ItemContainerStyle> |