如何从ContextMenu绑定到MVVM中的WPF DataGridColumn?

时间:2014-04-25 12:42:23

标签: wpf mvvm binding datagrid contextmenu

我有一个DataGrid,它有不同的列(TextBox,Combobox,DataPicker等),通过MVVM显示数据。现在我想让每个ColumnHeader上的ContextMenu按所选列分组,但是我无法访问Column的Binding Source(Binding Path)来告诉ViewModell它有哪些列分组。当我第一次打开上下文菜单时它工作正常,但是当我再次打开上下文菜单时,它仍然从第一次传递SortMemberPath。我做错了什么?

XAML:

<DataGrid.Resources>
    <ContextMenu x:Key="DataGridColumnHeaderMenu">
        <MenuItem Name="mi_group" Header="Grouping"                                             
                  Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}, Path=DataContext.GroupColumn}"
                  CommandParameter="{Binding Path=Column.SortMemberPath, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridColumnHeader}}">
        </MenuItem></ContextMenu>
    <Style TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="ContextMenu" Value="{StaticResource DataGridColumnHeaderMenu}" />
    </Style>
</DataGrid.Resources>

视图模型:

public ICommand GroupColumn
{
    get
    {
        if (groupColumn == null)
        {
            groupColumn = new RelayCommand( (param) => {

                    UngroupColumns.Execute(null);
                    string groupPropertyName = param as string;   ///Don't want this Switch. ViewModel doesn't know name of the header

                    switch (groupPropertyName)
                    {
                        case "Project": {groupPropertyName = "project_id"; break;}
                        case "Date":    {groupPropertyName = "date";       break;}
                        case "Person":  {groupPropertyName = "person_id";  break;}
                        default:        {groupPropertyName = null; break;        }
                    }

                    if (groupPropertyName != null)
                    {
                        MyData.GroupDescriptions.Add(new PropertyGroupDescription(groupPropertyName));
                        MyData.SortDescriptions.Add(new SortDescription(groupPropertyName, ListSortDirection.Ascending));
                    }
                });
        }

        return groupColumn;
    }
}

1 个答案:

答案 0 :(得分:0)

所以我终于找到了解决问题here的方法。 但是当我尝试使用时,我仍然不明白为什么CommandParameters没有更新:

CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridColumnHeader}}, Path=Column.SortMemberPath}"

所以这里的代码对我有用:

<DataGrid.Resources>    
<ContextMenu x:Key="DataGridColumnHeaderMenu">
    <MenuItem Name="mi_group" Header="Make Groups"                                             
              Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}, Path=DataContext.GroupColumn}"
              CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.Column.SortMemberPath}">                        
        <MenuItem.Icon>
            <Image Source="images/Treeview.png" />
        </MenuItem.Icon>
    </MenuItem>     
</ContextMenu>
<Style TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="ContextMenu" Value="{StaticResource DataGridColumnHeaderMenu}" />
</Style></DataGrid.Resources>

在我的案例中使用SortMemberPath的好处是我还可以检索DataGridComboxColumn的值(SelectedValuePath)。假设SelectedValuePath等于我的情况下的SortMemberPath。

视图模型:

    private RelayCommand groupColumn;
public ICommand GroupColumn
{
    get
    {
        if (groupColumn == null)
            groupColumn = new RelayCommand(
                (param) =>
                {
                    UngroupColumns.Execute(null);

                    // param contains SortMemberPath of the DataGridColumn
                    string groupPropertyName = param as string;

                    if (groupPropertyName != null)
                    {
                        MyData.GroupDescriptions.Add(new PropertyGroupDescription(groupPropertyName));
                        MyData.SortDescriptions.Add(new SortDescription(groupPropertyName, ListSortDirection.Ascending));
                    }

                });

        return groupColumn;
    }
}