2014-09-10 4 views
2

У меня есть стандартный WPF <DataGrid> со специфическими столбцами (то есть не сгенерированы автоматически). Он заполняется на C#, устанавливая ItemsSource в список объектов, которые имеют различные свойства, а различные столбцы в datagrid привязаны (через Binding = "{Binding XXX}" в XAML) к соответствующим свойствам.Хотите, чтобы пользовательское контекстное меню в ячейке datagrid WPF

Теперь я хочу, чтобы контекстное меню отображалось, когда пользователь щелкает правой кнопкой мыши по ячейке, но содержимое меню должно меняться в зависимости от того, какая ячейка пользователь нажимает. Я не могу понять, как это сделать, поэтому любые предложения будут оценены.

Идеальный сценарий состоит в том, что каждая ячейка в данном столбце (а не заголовок столбца) имеет одно и то же контекстное меню, а разные столбцы имеют разные контекстные меню. Некоторые элементы в меню могут быть серыми, если они не применяются к этой конкретной строке. Содержимое меню может быть жестко закодировано в зависимости от того, в какой столбец пользователь нажал, но я должен был бы иметь какой-то динамический механизм (в идеале через функцию C#, а не бесконечный XAML), чтобы решить, когда седеть из меню предметы, а когда нет.

EDIT: Я в порядке с решением, которое позволяет добавлять элементы меню динамически (в коде C#) по мере появления меню, если я могу определить, из какой ячейки он появляется. На самом деле я бы предпочел такую ​​вещь, поскольку мне нравится C# лучше, чем XAML.

ответ

1

Вот полный пример:

ВМ:

public class MainViewModel : INotifyPropertyChanged 
{ 
    public ObservableCollection<Employee> Employees { get; set; } 

    public RelayCommand<Employee> FireCommand { get; set; } 

    private Employee selectedEmployee; 
    public Employee SelectedEmployee 
    { 
     get { return selectedEmployee; } 
     set 
     { 
      if (value != selectedEmployee) 
      { 
       selectedEmployee = value; 
       PropertyChanged(this, new PropertyChangedEventArgs("SelectedEmployee")); 
       FireCommand.RaiseCanExecuteChanged(); 
      } 
     } 
    } 

    public MainViewModel() 
    { 
     Employees = new ObservableCollection<Employee> 
     { 
      new Employee{ Name = "Mickey Mouse", CanBeFired = true }, 
      new Employee{ Name = "Barack Obama", CanBeFired = true }, 
      new Employee{ Name = "Chuck Norris", CanBeFired = false /* Don't even try!!! */ } 
     }; 

     foreach (Employee e in Employees) 
     { 
      e.PropertyChanged += (s, a) => 
       { 
        if (a.PropertyName == "CanBeFired") 
        { 
         FireCommand.RaiseCanExecuteChanged(); 
        } 
       }; 
     } 

     FireCommand = new RelayCommand<Employee>(_ => Employees.Remove(SelectedEmployee), _ => SelectedEmployee != null && SelectedEmployee.CanBeFired); 
    } 

    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
} 

Часть XAML:

<DataGrid ItemsSource="{Binding Employees}" SelectedValue="{Binding SelectedEmployee}" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTemplateColumn> 
      <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Name}"></TextBlock> 
       </DataTemplate> 
      </DataGridTemplateColumn.CellTemplate> 
     </DataGridTemplateColumn> 
     <DataGridCheckBoxColumn Binding="{Binding CanBeFired,UpdateSourceTrigger=PropertyChanged}"></DataGridCheckBoxColumn> 
    </DataGrid.Columns> 
    <DataGrid.ContextMenu> 
     <ContextMenu> 
      <MenuItem Header="Fire" Command="{Binding FireCommand}"> 
      </MenuItem> 
     </ContextMenu> 
    </DataGrid.ContextMenu> 
</DataGrid> 

Обратите внимание, что вам не нужны дженерики RelayCommand, так что вы можете игнорировать общий параметром и параметрами лямбда _.

+0

Я в замешательстве - это даст мне одно и то же контекстное меню из 1 пункта (а именно «Огонь») в каждом столбце, верно? Мне нужно иметь различные контекстные меню для разных столбцов. Все это текстовые столбцы, если это помогает. Так, например, в первом столбце я хочу иметь контекстное меню с надписью «Огонь», но в столбце «Два» я хочу создать трехпозиционное контекстное меню с «Это», «Это» и «Другое». – MarkV

+0

Я бы сказал, что ContextMenu должен быть связан с TextBlock внутри DataTemplate – rpaulin56

+0

@Pragmateek Это было полезно. Можете ли вы разместить код для RelayCommand, пожалуйста? – vdidxho

Смежные вопросы