2013-10-18 51 views
4

在WPF中,使用MVVM light,有一個Class(它由一些學生組成),並且Class包含一些Student s。命令綁定到ContextMenu(它在ListBox中的ListBoxItem上)不起作用

enter image description here

右鍵點擊一個學生的名字,然後會顯示一個MessageBox,正是在這樣確定:

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> 

但是,它不工作這樣(使用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> 

,而不是

<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); 
      } 
     } 
    } 
} 

回答

3

可以在您使用的ContextMenu作爲一種資源?

喜歡的東西:

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

然後在列表中,這樣做:

<Listbox ContextMenu = {StaticResource contextMenuExample} ... /> 

還是你真的想使用ItemContainerStyle?

從 - >how to right click on item from Listbox and open menu on WPF

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

我只是想,只顯示文本菜單時,右鍵單擊一個ListBoxItem,而不是完整的ListBox。 – SubmarineX

+0

看看:http://stackoverflow.com/questions/9549231/how-to-right-click-on-item-from-listbox-and-open-menu-on-wpf – sexta13

+0

我不認爲他們如果使用ListBox.Resources是不同的。在我的應用程序中使用MVVM,所以它會更復雜。 – SubmarineX

1

通過移動的ContextMenu到ListBoxItem的,你從ClassDetailsViewModel(ListBox的DataContext的),以StudentViewModel(在ListBoxItem中的DataContext的)改變的DataContext。因此,您需要更改路徑以訪問父列表框的DataContext以訪問RelayCommand。

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

這樣,它也不起作用。 – SubmarineX

+0

它實際上是有效的,但只有在ContextMenu被定義爲資源時纔會出現一些奇怪的原因。 – Taras

相關問題