想要每个WPF数据网格单元格的自定义上下文菜单

时间:2014-09-10 22:07:07

标签: wpf datagrid

我有一个标准的WPF< DataGrid>具有特定列(即不自动生成)。它通过将ItemsSource设置为具有各种属性的对象列表填充在C#中,并且数据网格中的各个列通过XAML中的Binding =“{Binding XXX}”绑定到相应的属性。

现在,我想在用户右键单击单元格时显示上下文菜单,但菜单内容应根据用户单击的单元格而有所不同。我无法弄清楚如何做到这一点,所以任何建议都将不胜感激。

理想情况是给定列中的每个单元格(不是列标题)将具有相同的上下文菜单,并且不同的列将具有不同的上下文菜单。如果菜单中的某些项目不适用于该特定行,则它们可能会显示为灰色。菜单的内容可以根据用户点击的列进行硬编码,但是我必须有某种动态机制(理想情况下通过C#函数,而不是无限的XAML)来决定何时灰显菜单物品,什么时候不去。

编辑:我可以使用一个解决方案,让我在菜单出现时动态添加菜单项(在C#代码中),如果我可以告诉它出现的是哪个单元格。其实我更喜欢这样的事情,因为我比CAM更喜欢C#。

1 个答案:

答案 0 :(得分:1)

以下是完整的示例:

VM:

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,因此您可以忽略lambda的泛型参数和_参数。