如何从ContextMenu绑定到MVVM中的WPF DataGridColumn? [英] How to bind to WPF DataGridColumn in MVVM from ContextMenu?

查看:145
本文介绍了如何从ContextMenu绑定到MVVM中的WPF DataGridColumn?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



XAML:

 < DataGrid资源> 
< ContextMenu x:Key =DataGridColumnHeaderMenu>
< MenuItem Name =mi_groupHeader =分组
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 =ContextMenuValue ={StaticResource DataGridColumnHeaderMenu}/>
< / Style>
< /DataGrid.Resources>

ViewModel:

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

UngroupColumns.Execute(null);
string groupPropertyName = param as string; ///不要此Switch。ViewModel不知道标题名称

switch(groupPropertyName)
{
caseProject:{groupPropertyName =project_id; break;}
caseDate:{groupPropertyName =date ; break;}
casePerson:{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;
}
}


解决方案

我终于找到了解决问题的方法 here
但是我仍然不明白为什么CommandParameters在我尝试使用时不会更新:

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

所以这里是适用于我的代码:

 < DataGrid.Resources> 
< ContextMenu x:Key =DataGridColumnHeaderMenu>
< MenuItem Name =mi_groupHeader =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 =ContextMenuValue ={StaticResource DataGridColumnHeaderMenu}/>
< / Style>< /DataGrid.Resources>

在我的情况下使用SortMemberPath的优点是我还可以检索DataGridComboxColumn的值(SelectedValuePath) 。假设SelectedValuePath等于SortMemberPath,这在我的情况下。



ViewModel:

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

// param包含DataGridColumn的SortMemberPath
string groupPropertyName = param as string;

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

});

return groupColumn;
}
}


I have a DataGrid with different Columns (TextBox, Combobox, DataPicker, etc.) displaying Data via MVVM. Now I want to have ContextMenu on each ColumnHeader to Group by the selected column, but I can't access the Binding Source (Binding Path) of the Column to tell ViewModell which column it has to Group. When I open the context menu for the first time it works fine, but when I open the context menu once again, it still passes the SortMemberPath from the first time. What am I doing wrong?

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>

ViewModel:

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

解决方案

So I've finally found a solution to my problem here. But I still don't understand why CommandParameters is not updating when I try to use:

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

So here is the code that works for me:

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

The Advantage of using SortMemberPath in my case was that I could retrieve also a value (SelectedValuePath) for DataGridComboxColumn. Assumed that SelectedValuePath is equal to SortMemberPath which is in my case.

ViewModel:

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

这篇关于如何从ContextMenu绑定到MVVM中的WPF DataGridColumn?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆