对 DataGrid 组进行排序

2024-03-27

我有一个非常基本的DataGrid以及一些测试数据。数据作为ObservableCollection<T> of Client objects, 其中包含Organization, FirstName and LastName特性。我将项目分组为Organization并希望能够排序FirstName and LastName在特定组内(这部分功能正常),并且还对组本身进行排序Organization。最后一部分是我遇到问题的部分。

如果我没有指定任何排序属性或者如果我指定了属性CollectionViewSource.SortDescriptions(见下文),例如PropertyName="Name" or PropertyName="CompleteNonsense", 除了PropertyName="Organization",它会让我进行初始排序。如果您查看下图,会发现公司名称的显示顺序是乱序的,因为这就是集合的初始化方式。如果我点击Organizationheader,它会按升序对其进行排序,但之后不会再让我进行任何排序。如果我再次单击标题,它会更改指示排序方向的箭头,但不会发生实际排序。无论我指定什么排序属性,都会执行相同的操作...即使是完全任意的属性,除非它是PropertyName="Organization",或者如果没有指定属性。

如果我指定排序PropertyName="Organization",它将开始按升序排序,但如果单击标题则不会排序。因此,该属性名称似乎确实触发了排序,但只是第一次。

截屏:

这是XAML为了DataGrid:

<DataGrid ItemsSource="{Binding Source={StaticResource GroupedData}}" 
          AutoGenerateColumns="False" IsReadOnly="True" 
          GridLinesVisibility="None" HeadersVisibility="Column" 
          CanUserAddRows="False" CanUserDeleteRows="False"
          CanUserResizeRows="False" Background="White">
    <DataGrid.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="BorderThickness" Value="0"/>
        </Style>
    </DataGrid.CellStyle>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="Margin" Value="10,0,0,0"/>
        </Style>
    </DataGrid.RowStyle>
    <DataGrid.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <DockPanel Background="LightBlue" DataContext="{Binding Items}">
                        <TextBlock Text="{Binding Path=Organization}" 
                                   Foreground="Blue" Margin="5,0,0,0" Width="100"/>
                        <TextBlock Text="Employee Count:" Foreground="Blue" Margin="40,0,0,0"/>
                        <TextBlock Text="{Binding Path=Count}" Foreground="Blue" 
                                   Margin="5,0,0,0"/>
                    </DockPanel>
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </DataGrid.GroupStyle>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Organization" Binding="{Binding Organization}"/>
        <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
        <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
        <DataGridTextColumn Width="*"/>
    </DataGrid.Columns>
</DataGrid>

这是XAML为了Grouping and Sorting:

<CollectionViewSource Source="{Binding Data}" x:Key="GroupedData">
    <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="Organization"/>
    </CollectionViewSource.GroupDescriptions>
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="Organization"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

有谁知道我如何实现组的排序Organization超出了最初的排序?

EDIT:

我一直在搞乱这个(真的需要弄清楚这一点)并为标题创建了一个快速的代码隐藏事件处理程序Click event:

<DataGrid.ColumnHeaderStyle>
    <Style TargetType="DataGridColumnHeader">
        <EventSetter Event="Click" Handler="ColumnHeader_Click"/>
    </Style>
</DataGrid.ColumnHeaderStyle>
private void ColumnHeader_Click(object sender, RoutedEventArgs e)
{
    var columnHeader = sender as DataGridColumnHeader;
    if (columnHeader != null && columnHeader.Content.ToString().Equals("Organization"))
    {
        if (columnHeader.Column.SortDirection == ListSortDirection.Descending)
        {
            columnHeader.Column.SortDirection = ListSortDirection.Ascending;
            MessageBox.Show("Ascending");
        }
        else
        {
            columnHeader.Column.SortDirection = ListSortDirection.Descending;
            MessageBox.Show("Descending");
        }
    }
}

每次点击后Organization, "Descending"弹出,排序箭头指向下方,点击后OK,它立即恢复到指向上方。组的实际排序永远不会在视觉上进行。有什么东西让它卡在一个Ascending order.


Note:参见Edit获取最新代码。

这有点棘手,但我找到了答案。下面的代码用于代码隐藏处理程序Sorting事件,但可以轻松调整以放置在ViewModel or View(取决于你如何做事)。

Code:

<DataGrid Sorting="DataGrid_Sorting" ... > ... </DataGrid>
private void DataGrid_Sorting(object sender, DataGridSortingEventArgs e)
{
    var headerName = "Organization";

    var column = e.Column;
    if (!column.Header.ToString().Equals(headerName))
    {
        return;
    }

    var source = (sender as System.Windows.Controls.DataGrid).ItemsSource as ListCollectionView;
    if (source == null)
    {
        return;
    }

    e.Handled = true;
    var sortDirection = column.SortDirection == ListSortDirection.Ascending ? 
        ListSortDirection.Descending : ListSortDirection.Ascending;

    using (source.DeferRefresh())
    {
        source.SortDescriptions.Clear();
        source.SortDescriptions.Add(new SortDescription(headerName, sortDirection));
    }
    source.Refresh();
    column.SortDirection = sortDirection;
}

使用上面的代码,组本身按以下方式排序Organization每组中的项目按以下顺序排序FirstName and LastName。希望这段代码对其他人有帮助。我一整天都在四处寻找,这似乎是人们在与群体打交道时面临的一个常见问题DataGrid.

唯一的缺点是,当组项目按分组属性以外的任何方式排序时,它会将组的顺序重置为默认值。在尝试了很多代码之后,我一直无法找到解决方案。如果有人找到该部分的解决方案,我很乐意给他们“正确答案”。

一些对我有帮助的资源:

如何在 WPF 中强制 DataGrid 组顺序? https://stackoverflow.com/a/10365727/2006048
WPF Datagrid 分组和排序 https://stackoverflow.com/a/16054823/2006048

EDIT:

弄清楚了关于组间排序被组内排序重置的最后一部分。这有点乱,因为我没有时间清理它,但我想我应该分享我的代码:

<CollectionViewSource.GroupDescriptions>
    <PropertyGroupDescription PropertyName="Organization"/>
</CollectionViewSource.GroupDescriptions>
<CollectionViewSource.SortDescriptions>
    <scm:SortDescription PropertyName="Organization" Direction="Ascending"/>
    <scm:SortDescription PropertyName="FirstName" Direction="Ascending"/>
    <scm:SortDescription PropertyName="LastName" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
private void DataGrid_Sorting(object sender, DataGridSortingEventArgs e)
{
    SortGroupedDataGrid("Organization", sender, e);
}

private void SortGroupedDataGrid(string groupHeader, object sender, DataGridSortingEventArgs e)
{
    // Get the main ListCollectionView and make sure it's not null.
    var source = (sender as System.Windows.Controls.DataGrid).ItemsSource as ListCollectionView;
    if (source == null)
    {
        return;
    }

    // Mark event as handled, so that automated sorting would not take place.
    e.Handled = true;
    // Main header which was used for the grouping.  I'm only using one, but more can be added.
    var headerName = groupHeader;
    // Get the column that was being sorted on.
    var column = e.Column;
    // Check if the column was the same as the one being used for the grouping.
    // I remove spaces so that any properties I use match the headers.  Regex would probably
    // work just as well, but it's an overkill for me at this time.
    var isMainHeader = column.Header.ToString().Replace(" ", "").Equals(headerName);
    // Because I set the initial sorting for all the properties in the XAML to be
    // be sorted in Ascending order, I set these ones to Descending.  One is for
    // the main column and the other is for the secondary column.  This does not account
    // for a case where user Shift + Clicks multiple columns to chain sort.
    var mainSortDirection = ListSortDirection.Descending;
    var secondarySortDirection = ListSortDirection.Descending;

    // If this is a main column sort event...
    if (isMainHeader)
    {
        // Check its sorting direction and set it as opposite.
        mainSortDirection = column.SortDirection == ListSortDirection.Descending ?
            ListSortDirection.Ascending : mainSortDirection;
    }
    else
    {
        // ...else, get the sorting direction of the main column, because we want
        // it to stay the same, and get the opposite sorting direction for the
        // secondary column.
        mainSortDirection = source.SortDescriptions[0].Direction;
        secondarySortDirection = column.SortDirection == ListSortDirection.Descending ?
            ListSortDirection.Ascending : secondarySortDirection;
    }

    // Defer refreshing of the DataGrid.
    using (source.DeferRefresh())
    {
        // Clear any existing sorts.  I've had some issues trying to alter existing ones.
        source.SortDescriptions.Clear();
        // Since we want main column to either alter if its sort event was called, or
        // stay the same if secondary column event was called, we always set it first.
        source.SortDescriptions.Add(new SortDescription(headerName, mainSortDirection));

        // If this was not a main column event...
        if (!isMainHeader)
        {
            // ...then set sorting for that other column. Since it'll be at index 1, 
            // after the main one, it'll only sort within each group, as I wanted.
            source.SortDescriptions.Add(new SortDescription(column.Header.ToString().Replace(" ", ""), secondarySortDirection));
            // Set the header direction as well.
            column.SortDirection = secondarySortDirection;
        }
        else
        {
            // Otherwise, it's a main event and we want to show the error for its header.
            // If you want primary sorting direction to always display, then simply take
            // it outside of else scope, so that it's always assigned.
            column.SortDirection = mainSortDirection;
        }
    }
    // Now we can refresh and post changes.
    source.Refresh();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对 DataGrid 组进行排序 的相关文章

  • MigraDoc 项目符号列表(漏洞)

    在我的解决方案中 我在 PDF 文件中使用项目符号列表 它看起来像这样 Solcellepaneler kr ver hverken autoriseret service eller tidskr vende vedligehold So
  • 枚举 EMF 时丢失文本

    我在列举发票 emf http www mediafire com kdjwvvo7odyvwa6并将其复制到另一个但文本丢失了 令人惊讶的是 当我将其输出到窗口时 它绘制得非常完美 int CALLBACK EnhMetaFileProc
  • 获取不带波形符的泛型类名称[重复]

    这个问题在这里已经有答案了 我正在尝试获取类型名称T使用这个 typeof T Name 班级名称是ConfigSettings 而不是返回ConfigSettings它正在返回ConfigSettings 1 有什么具体原因吗 我怎样才能
  • 如何获取 PropertyGrid 的单元格值 (c#)?

    如何在 C 中获取属性网格项和项的值 例如 Name Ali LastName Ahmadi Name 和 LastName 是 propertygrid 的 2 个属性 PropertyGrid只是对象的组件模型表示的视图 我会说 查看组
  • C++在子类中调用虚方法

    我有以下课程 class A protected A inner public virtual void doSomething 0 class B public A void doSomething if inner NULL inner
  • Apple IOS 上的 C# 应用程序 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有基于 C Net 的应用程序 有什么方法可以在 Apple IOS 上运行这些应用程序吗 我没有资
  • C# While 循环与 For 循环?

    在 C 中 一个问题已经困扰我一段时间了 它的 While 和 For 循环之间的实际主要区别是什么 它只是纯粹的可读性吗 在 for 循环中本质上可以做的所有事情都可以在 while 循环中完成 只是在不同的地方 举这些例子 int nu
  • 获取进程的所有 DLL

    我想获取为给定进程加载的所有 dll 的列表 我目前正在使用 NET框架4 0 我知道有一个bug https connect microsoft com VisualStudio feedback details 546430 syste
  • 使用 c# 中的 c++ ref 中的引用从 C# 调用 C++ 代码错误

    所以在我的 c dll 文件中我得到了以下函数 DLL void GetUserPass char userName char passWord userName ceva passWord altceva 现在我想从 c 调用它 但它给了
  • vs2010 c++ 通过debug查看指针内容

    我正在使用 Vs2010 c 处理 2D 数组 我从一维指针开始 并使用操作 如下 class CMatrix void clear public int nRows int nCols short MyMat CMatrix CMatri
  • cmake 包括其他目录中的 h 文件

    我在 cmake 项目下进行测试时遇到问题 我的项目是这样安排的 TerrainMap PointAccumulator heightQuadGrid Test 在 TerrainMap 目录中 CMakeLists txt 文件简单地概述
  • 如何在PropertyGrid中自定义绘制GridItem?

    我想以与所有者在 ListView 详细信息 和其他控件中绘制项目类似的方式在 PropertyGrid 中绘制属性值 如果将属性声明为 Color 类型 则其值将使用字符串描述旁边的颜色样本来绘制 如果属性是图像类型 则在字符串描述旁边绘
  • 当一种语言是另一种语言的平行超集时,这意味着什么?

    我正在阅读关于实时并发 C 的期刊文章 http link springer com article 10 1007 2FBF00365999 并且它在摘要中提到 因此你们中的任何人都可以通过该链接查看上下文 Concurrent C 是
  • Sharepoint 的 CAML 查询中的日期时间比较

    我正在尝试从共享点列表中获取某些项目 具体取决于自定义列中的日期 我已经使用 U2U Caml Builder 创建了查询 这很有效 但是当我将其放入 Web 部件中自己的代码中时 它总是返回列表中的所有项目 这是我的代码 DateTime
  • 比较 C# 中的对象属性[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动
  • 如何重写(重新实现)QFileSystemModel 中的成员函数

    我已经为此苦苦挣扎了一段时间 Qt s QFileSystemModel由于图标获取算法非常糟糕 在获取数百个文件时速度非常慢 我想完全禁用图标 它们被提取到QFileSystemModel data方法不是虚拟的 QFileSystemM
  • 如何从 WPF 应用程序访问 Windows 文件预览图标

    我在一个目录中有一堆图片和视频 需要在WPF应用程序中显示 我正在考虑将Win7大图标本身显示为预览图像 因为这将节省我从视频文件中抓取适当帧的工作 因为 Windows 已经很好地完成了这项工作 有任何代码片段可以访问此 Shell 图标
  • 我可以创建一个 List> 吗?

    我正在尝试创建一个列表WeakReference使用 4 5 泛型实现 这样我就可以避免类型检查和转换WeakReference目标 但 WeakReference
  • WPF Datagrid 组扩展文本 - 如何绑定?

    我正在使用带有组合框的数据网格 该组合框应该更改分组字段 我使用以下 xaml 来定义常规分组模板
  • Image.Save 异常“GDI+ 中发生一般错误。”保存到 MemoryStream 时

    我有一个服务器客户端应用程序 我想从服务器获取屏幕截图 但在线bitmap Save ms System Drawing Imaging ImageFormat Png 我得到这个例外 A generic error occurred in

随机推荐

  • FCM 获取 MismatchSenderId

    我有一个使用 Google FCM 发送推送通知的应用程序 当我向一组用户发送推送通知时 我得到的响应是MismatchSenderId对于其中一些人来说 尽管如此 所有用户都拥有完全相同的应用程序 如何某些用户获得成功响应 而其他用户获得
  • iphone如何通过Xcode拍照后进入图片库

    大家好 我正在实施以下代码来通过我的应用程序拍照 UIApplication sharedApplication keyWindow setRootViewController picker picker sourceType UIImag
  • 找不到模块 create-react-app/script/start.js

    我的程序结构发生了一些变化 由于其复杂性 我无法准确指出问题所在 自从我的应用程序崩溃并且不再工作以来 我尝试了不同的方法 例如删除节点模块包并重新安装它们 但仍然无法工作 每当我尝试跑步时npm 启动我收到以下错误 below is my
  • 使用密码保护关闭的工作簿

    我已经搜索过 但没有找到在关闭的工作簿上添加外部密码的方法 假设我已经关闭了名为 Sample xlm 的工作簿 并且我正在打开一个名为 Test xlm 的工作簿 是否有代码可以让我在 Sample xlsm 上设置密码 我的意思是外部密
  • 空状态页面和导航器问题?

    我想实施空状态页 https material io design communication empty states html content在 Flutter 应用程序中 当新闻源为空时 当提要中没有活动时 我想显示 没有活动 当数据
  • 如何将服务变量与组件 Angular 2 绑定?

    我有一个变量 public tick number 在服务中 该服务注入了另一个服务计时器 它的启动方式如下 class Service constructor public timer TimerService public sendSm
  • Python 和类似字典的对象

    我需要一个用于字典的 python 3 1 深度更新函数 该函数将递归更新父字典内的子字典 但我认为 将来 我的函数可能必须处理行为类似于字典但实际上并非如此的对象 此外我想避免使用isinstance and type 因为它们被认为是不
  • 无法运行 React-Native UIExplorer 示例项目

    我一直在尝试在 Windows 上运行 UIExplorer 项目 我收到以下错误 make D react native ReactAndroid build tmp buildReactNdkLib local armeabi v7a
  • Gunicorn + nginx:通过套接字还是代理服务器?

    我见过两种使用 Gunicorn 和 nginx 托管 django 应用程序的策略 一种策略是在网络端口上运行 Gunicorn 例如 来自goodcode https goodcode io articles django nginx
  • jQuery TouchSwipe 插件不适用于链接?

    我正在使用 jQuery TouchSwipe 插件 它在 div 上工作得很好 但在链接上根本不起作用 我想要它 因此如果您点击或单击链接 您将获得默认的链接行为 但是如果你滑动 我希望 javascript 滑动能够像元素是 div 一
  • Java 相当于 .NET Action 和 Func 等[重复]

    这个问题在这里已经有答案了 Java 中是否有标准的通用 回调 或 函数 方法 类型 例如System Action
  • ASP.NET 网站项目何时重新编译?

    As Maurico https stackoverflow com users 21239 mauricio scheffer and codeka https stackoverflow com users 241462 codeka首
  • 如何使用 Ecto 的时间戳向现有表添加时间戳?

    Since inserted at and updated at不可能是null这是行不通的 def change do alter table channels do timestamps end end Postgrex Error E
  • 在 Outlook 2013 中调用功能区按钮

    我们有一个 Outlook 插件 我们需要以编程方式取消任务项检查器窗口中的任务分配 就像取消分配按钮一样 人们会认为调用TaskItem CancelResponseState 可能会起作用 虽然它确实取消了分配 但它也使任务处于不可分配
  • 使用 RequestAnimationFrame 实现准确计时

    到目前为止 我还没有找到很多关于这个主题的文档 我的总体感觉是 在为浏览器实现动画时 最好使用 RequestAnimationFrame 而不是 bog 标准 JavaScript 计时器 我的理解是计时器不可靠 并且它们的分辨率在不同浏
  • Windows 8 Phone - 访问 NFC 读卡器?

    简短的问题 我可以使用支持 NFC 的 Windows Phone 8 读取信用卡信息吗 长问题 NFC 与信用卡如何工作 卡 或具有钱包功能的手机 通过 NFC 接收请求并以某种标准化格式回复明文信用卡信息 那么 钱包选项在广播信用卡信息
  • 传送仅公开 C api 的 C++ dll

    我正在编写一个软件 其 API 仅为 C 语言 因为很容易将 C 代码与其他软件 客户端链接起来 然而 实际的程序代码是用 C 完成的 使用所有常见的 C 功能 如异常 STL 等 导出的 API 标头本身将用纯 C 编写 其中export
  • 如何使用 pandas tz_convert 转换为多个不同时区

    我有一些数据如下所示hour以世界标准时间 UTC 表示 我想创建一个名为的新列local hour基于time zone 我怎样才能做到这一点 好像是熊猫的tz convert不允许列或 pandas 系列作为输入tz争论 Create
  • Rails ActionController::Metal 的实际作用是什么

    我想了解一下Rails ActionController 金属控制器 我读过相关内容here http api rubyonrails org classes ActionController Metal html但不完全理解 它用于构建
  • 对 DataGrid 组进行排序

    我有一个非常基本的DataGrid以及一些测试数据 数据作为ObservableCollection