Microsoft-ui-xaml: 讨论:现代 WinUI DataGrid - 需要输入

创建于 2019-10-28  ·  81评论  ·  资料来源: microsoft/microsoft-ui-xaml

讨论:现代 WinUI DataGrid

嘿社区成员! 我们已经看到,对于你们中的许多人来说,DataGrid 一直是 Windows 社区工具包的重要组成部分,我们有兴趣将其升级为本机 WinUI 控件 (!!)。 我需要你的帮助来弄清楚需要什么才能使完整的 DataGrid 达到最佳状态。

我想听听您对 DataGrid 的所有意见。 首先,鼓励尽可能多地回答您有时间的问题:

  1. 您希望 DataGrid 有哪些愿望清单项目?
  2. DataGrid 在 UI、UX 和整体设计方面可以改进哪些方面?
  3. 您喜欢/不喜欢 DataGrid 的哪些方面?
  4. 您在哪些场景中使用了 DataGrid?
  5. 有没有您希望它更适合的场景?

提前谢谢大家! 有关一些复习和上下文,请参阅以下链接。

相关链接


阅读DataGrid 文档
通过DataGrid Nuget 包下载下载 DataGrid并与之交互
通过查看WCT 中现有的

discussion

最有用的评论

我的愿望清单:对我来说,一个好的数据网格默认包含以下所有功能。 我从 html 世界借用了一些屏幕截图。

使用首选行数轻松过滤整个页面。

1

选择/取消选择可见列、列排序、复制、打印

2

将数据导出为特定格式。

3

通过拖动列重新排序列。

4

列过滤

5

固定标题 - 即使滚动时标题也保持在顶部

带有 XAML 模板的行详细信息以获取详细信息。

6

行分组

7

拖放行顺序

8

在我看来,上述功能应该是所有数据网格的标准配置。

如果您想让 datagrid 在 html 世界中脱颖而出,那么我还将包括以下内容。 我发现自己多次查看数据网格,然后在列表视图上解决,因为数据网格缺少这些功能。

侧滑行以包含编辑、删除、标记等功能。

sideswipe

上述功能主要处理“数据的呈现”,WinUI 仍然缺乏的是我认为应该是像Microsoft Pivot Control这样的原生 WinUI 功能(控件)

MS 已经有了这方面的源代码,这在当时绝对是一个很棒的控件。

pivot1

https://www.youtube.com/watch?v=ZJIkQ9nebKY

现在,您将介绍数据的可视化,这应该是将 WinUI 与现有的所有基本功能区分开来的最低要求。

最重要的是,它真正展示了“本机应用程序”的力量,这些应用程序应该包括令人敬畏的动画和视觉上吸引人的强大且看起来非常酷的控件。

我可以更进一步说,在上述功能(可视化)之后,我们可以包含 2D/3D 动画,在数据中创建深度概念并将我们带到不同的平流层,但我想那是另一天; ))

uwp2

所有81条评论

更多视图模式。 看看文件资源管理器和它的图标视图。 DataGrid 应该能够在带有分组的网格中显示图标/项目,以及带标题的行和列。

我知道这可能是不可能的,或者超出范围 - 但它是 WinUI 与 Win32 的一个方面,不像 1:1 那样简单 - 以及现代版本的文件资源管理器或通用文件对话框 - 可能需要这样的控制。 这可能是该控件,而不是内部自定义控件。

我的愿望清单:对我来说,一个好的数据网格默认包含以下所有功能。 我从 html 世界借用了一些屏幕截图。

使用首选行数轻松过滤整个页面。

1

选择/取消选择可见列、列排序、复制、打印

2

将数据导出为特定格式。

3

通过拖动列重新排序列。

4

列过滤

5

固定标题 - 即使滚动时标题也保持在顶部

带有 XAML 模板的行详细信息以获取详细信息。

6

行分组

7

拖放行顺序

8

在我看来,上述功能应该是所有数据网格的标准配置。

如果您想让 datagrid 在 html 世界中脱颖而出,那么我还将包括以下内容。 我发现自己多次查看数据网格,然后在列表视图上解决,因为数据网格缺少这些功能。

侧滑行以包含编辑、删除、标记等功能。

sideswipe

上述功能主要处理“数据的呈现”,WinUI 仍然缺乏的是我认为应该是像Microsoft Pivot Control这样的原生 WinUI 功能(控件)

MS 已经有了这方面的源代码,这在当时绝对是一个很棒的控件。

pivot1

https://www.youtube.com/watch?v=ZJIkQ9nebKY

现在,您将介绍数据的可视化,这应该是将 WinUI 与现有的所有基本功能区分开来的最低要求。

最重要的是,它真正展示了“本机应用程序”的力量,这些应用程序应该包括令人敬畏的动画和视觉上吸引人的强大且看起来非常酷的控件。

我可以更进一步说,在上述功能(可视化)之后,我们可以包含 2D/3D 动画,在数据中创建深度概念并将我们带到不同的平流层,但我想那是另一天; ))

uwp2

一个很好的起点是查看您的合作伙伴 Telerik 及其 RadDataGrid(UWP 开源)。 我和我的一位客户一起使用了它,它实际上运行良好。 它速度极快且用途广泛。 唯一困难的是他们的代码,如果对架构没有很好的理解,就无法从他们的引擎中修改任何内容。

我希望新的 DataGrid 与 Telerik 一样高效。

我很高兴看到 WinUI 团队正在考虑使用 DataGrid 控件。

我希望从替换 Toolkit DataGrid 的新控件中看到的最实质性改进:

  • 通过索引检索 DataGridRow 的能力
  • 特定于 DataGridRows 本身的事件。 例如,DoubleTapped 和 RightTapped。
  • 平滑滚动
  • 单元重命名的输入验证
  • 专为行图标设计的 DataGridColumn
  • 轻松定制颜色等。

有一个编辑按钮的选项将可拖动的图标放在每行旁边以移动订单,这将是一个有用的功能。 看到行后面的一些阴影被抬起和移动也会很棒(因为 Fluent 的主要属性之一是深度)。 拖动图标旁边的小向上和向下箭头可能会很好地使用鼠标输入更轻松地移动行。 如果使用箭头移动一行,一个微妙的滑动动画将是一个很好的接触。 使用触摸输入,按住一行并移动它甚至不需要按下编辑按钮的选项也可能很好用。 我不确定这是否已经得到支持,但我可以看到文件资源管理器中的选择复选框,明确哪些 DataGrids 支持行选择,并且只是改进了整体 UX。 iOS 提醒应用程序包含其中一些想法(下图示例)。 iOS Stocks 应用程序也有类似的处理可移动行的方式。 大多数这些想法也适用于专栏。

123456

IMG_1820 (1)

@NoahFeller这种类型的操作对于列表视图更有意义。 使用 Grid 视图,您不会重新排列顺序,应该有排序选项,但用户不会拖动东西。

*编辑
仔细考虑之后,我确实看到了这样的选项是多么有用。 但是,我绝对不认为这应该是默认行为。

@NoahFeller这种类型的操作对于列表视图更有意义。 使用 Grid 视图,您不会重新排列顺序,应该有排序选项,但用户不会拖动东西。

*编辑
仔细考虑之后,我确实看到了这样的选项是多么有用。 但是,我绝对不认为这应该是默认行为。

是的,你可能是对的@yaichenbaum。 我将这些建议设想为进行自定义排序的能力,我认为拖动可能对此有用。 所以我同意,绝对不是默认值,但它作为一种选择可能非常有用。 感谢您的反馈!

WPF 数据表到数据网格函数的简单性。 过去一周左右,我实际上一直在努力使 UWP 数据网格能够正常工作,我可以在 WPF 中使用它,我可以将数据网格绑定到数据视图,然后使用 datatable.defaultview 从 SQL 填充数据视图。 然后网格只显示数据表。 做起来非常简单,而到目前为止,UWP 已经让这件事变得异常复杂。

使其跨平台

我想请求一个单单元格选择模式,excel 样式。
最终目标是一种具有与 WinForms DataGridView 完全相同行为的模式。

拥有可以支持不同用例的各种虚拟化选项(从简单的滚动虚拟化选项,如回收到其他概念,如数据分页)
通常(在支持此功能的类似桌面控件中)其中一些选项在与具有唯一数据的列的自定义模板一起使用时开始失败。 在这些情况下,他们能支持的越多越好。

如果可能的话,应该同步 Paging Control #268 提案,并将任何需要的钩子添加到 DataGrid 控件中。

这是个好消息! 自从它出现在社区工具包中以来,我一直在等待 DataGrid 前端的一些正式内容。 这确实是 WinUI 3.0 中缺少的最后一个控件,社区工具包没有很好的替代方法。

首先,请不要重新发明轮子。 作为 DataGrid 的 WPF 实现的基础(我知道您不能使用代码,但请使用 100% 的 API)——而不是 Silverlight。 WPF DataGrid 功能更加完整,并且在我的测试中错误更少。

在使用社区工具包 DataGrid 时,我还请求了以下针对各种用例讨论的API 添加:

  • RowPressed :如上所述。 表示已按下一行,以便可以进行进一步处理或上下文菜单。
  • RowDoublePressed :与 RowPressed 相同,只是双击版本。
  • ColumnHeaderPressed :每当按下列标题时发生。 必须优先于任何排序方向内部更新。 这将允许自定义过滤菜单或右键单击选项来打开/关闭列。
  • ColumnHeaderDoublePressed :与 ColumnHeaderPressed 相同,只是双击版本。
  • ColumnHeaderWidthChanged :每当用户调整列标题宽度时发生。 这将允许以干净的方式保存此信息。 这在恢复 UI 状态时通常需要。

在 ItemsSource 更改后,社区 takeit DataGrid 将滚动位置重置为顶部,我也继续遇到很多问题。 这需要得到修复,以便像在 WPF 中一样保留偏移量; 但是,我们还需要能够控制这一点,这也是我建议使用以下 API 的原因:

  • FirstRowInView() :返回用于恢复状态的 DataGrid 中可见的第一行。
  • VerticalOffset : 再次获取/设置以恢复滚动条的状态
  • Horizo​​ntalOffset : 获取/设置以恢复滚动条的状态

@RBrid也有一些分析帮助这里

建议的新事件,以及对现有事件的一些改进:

| 活动 | 评论 |
| :--- | :--- |
| ContextRequestedForColumnHeader | 支持在右键单击列标题时显示上下文菜单(或其他弹出)。 与Windows.UI.Xaml.UIElement.ContextRequested相同,但用于列标题而不是整个 DataGrid。 |
| ContextCanceledForColumnHeader | 与Windows.UI.Xaml.UIElement.ContextCanceled相同,但用于列标题而不是整个 DataGrid。 |
| ContextRequestedForRow | 支持在右键单击行时显示上下文菜单(或其他弹出)。 与Windows.UI.Xaml.UIElement.ContextRequested相同,但适用于行而不是整个 DataGrid。 |
| ContextCanceledForRow | 与Windows.UI.Xaml.UIElement.ContextCanceled相同,但适用于行而不是整个 DataGrid。 |
| RowTapped | 另请注意点击已选择的行的情况。 |
| RowDoubleTapped | 与Windows.UI.Xaml.UIElement.DoubleTapped相同,但适用于行而不是整个 DataGrid。 |
| RowRightTapped | 与Windows.UI.Xaml.UIElement.RightTapped相同,但适用于行而不是整个 DataGrid。 另见ContextRequestedForRow 。 |
| PointerPressedInRow | 与Windows.UI.Xaml.UIElement.PointerPressed相同,但适用于行而不是整个 DataGrid。 |
| PointerReleasedInRow | 与Windows.UI.Xaml.UIElement.PointerReleased相同,但适用于行而不是整个 DataGrid。 |
| PointerMovedInRow | 与Windows.UI.Xaml.UIElement.PointerMoved相同,但适用于行而不是整个 DataGrid。 可能只有在捕获指针时才会触发PointerMovedInRow 。 |
| ColumnHeaderTapped | 另请注意点击已选择的列标题的情况。 |
| ColumnHeaderDoubleTapped | 与Windows.UI.Xaml.UIElement.DoubleTapped相同,但用于列标题而不是整个 DataGrid。 |
| ColumnHeaderRightTapped | 与Windows.UI.Xaml.UIElement.RightTapped相同,但用于列标题而不是整个 DataGrid。 另见ContextRequestedForColumnHeader 。 |
| ColumnHeaderWidthChanged | 或者可以命名为ColumnHeaderResized 。 在事件 args 中,包含一个布尔属性,用于指定它是由用户更改还是以编程方式更改。 显然,事件参数还应指定调整/更改了哪个列标题。 |
| SortOrderChanged | 应在所选列标题列表更改时触发。 当任何选定的列在升序和降序之间切换时也会触发。 在事件 args 中,包含一个布尔属性,用于指定排序顺序是由用户更改还是以编程方式更改。 另见预先存在的事件Sorting 。 我认为如果排序没有取消,在触发Sorting事件后会触发一个新的事件SortOrderChanged 。 |
| Sorting | 已经存在,但考虑在允许取消排序请求的事件参数中添加一个可设置的布尔属性。 例如,排序可能无效或无法进行,需要取消排序。 还添加一个布尔属性来指定排序是由用户请求还是以编程方式请求。 |
| ColumnSortDirectionChanged | 这个事件可以被创建,但如果前面提到的SortOrderChanged事件被创建,如果SortOrderChanged在排序方向改变时也被触发,则它可能是不必要的。 |
| ColumnDisplayIndexChanged | 已经存在,但请考虑添加一个布尔属性(在事件参数中),指定它是由用户更改还是以编程方式更改。 另外,请说明为什么需要同时拥有ColumnDisplayIndexChangedColumnReordered事件。 或者,消除这些事件之一。 |
| ColumnReordered | 已经存在,但请考虑添加一个布尔属性,指定它是由用户更改还是以编程方式更改。 |
| SelectionChanged | 已经存在,但请考虑添加一个布尔属性(在事件参数中),指定它是由用户更改还是以编程方式更改。 |
| CopyingRowClipboardContent | 已经存在,但请考虑向事件 args 添加一个布尔属性,指定操作是否被剪切而不是复制。 或者制作一个单独的事件进行剪切。 |
| CuttingRowClipboardContent | 不存在。 考虑创建一个在用户尝试剪切行时触发的事件(通过 control-X 热键、上下文菜单或其他方式)。 或者使上述布尔属性允许CopyingRowClipboardContent复制和剪切操作触发
| PastingRowClipboardContent | 不存在。 考虑创建一个在用户尝试粘贴时触发的事件(通过 control-V 热键、上下文菜单或其他方式)。 |

我认为对我来说最重要的功能是能够轻松处理一百万行或更多行,而不必将一百万行加载到内存中。 ISupportIncrementalLoading 接口对此还不够好,因为滚动条仅反映您到目前为止已加载的行数(不是总数),要达到 100 万行,您必须继续滚动到最后并加载越来越多的数据,希望我不会耗尽内存。 但是如果我知道我有 100 万条数据记录,让我告诉数据网格,如果我快速滚动或跳到最后,我可能会被要求只提供最后几行。
考虑滚动我将动态引入的数据库中的行列表。

我认为对我来说最重要的功能是能够轻松处理一百万行或更多行,而不必将一百万行加载到内存中。 ISupportIncrementalLoading 接口对此还不够好,因为滚动条仅反映您到目前为止已加载的行数(不是总数),要达到 100 万行,您必须继续滚动到最后并加载越来越多的数据,希望我不会耗尽内存。 但是如果我知道我有 100 万条数据记录,让我告诉数据网格,如果我快速滚动或跳到最后,我可能会被要求只提供最后几行。
考虑滚动我将动态引入的数据库中的行列表。

这个。

“现代”意味着轻量级和快速,企业应用程序通常是通过对大量内部数据进行分类以查找和探索适当的记录。 分页、排序、异步增量加载、无限滚动——所有这些都是利用数据网格的桌面应用程序的主要内容。

MS 应该制作一个示例应用程序,在新网格中突出显示这些功能,并随着时间的推移收集企业开发人员的反馈,以改善这些体验。 让它运行像 World Wide Importers 这样的大型数据集来证明它的有效性。

@dotMorten

我认为对我来说最重要的功能是能够轻松处理一百万行或更多行,而不必将一百万行加载到内存中。

我也希望如此。 为了帮助支持一百万行(我的意思是帮助,不一定是完整的解决方案),我建议 DataGrid 应该使其当前的数据绑定技术成为可选的。 我相信当前数据绑定是强制性的(除非我的知识不再是最新版本的 DataGrid)。 DataGrid 不应要求使用Windows.UI.Xaml.Data.Binding作为检索每个可见行中每个单元格/列的值的唯一支持方式。

我建议 DataGrid 允许应用程序为 DataGrid 提供一个委托或接口实例,每当 DataGrid 需要检索一行中的单元格/列的值时,DataGrid 将调用该实例(或者,该委托或接口可以检索整行——所有列值对于指定的行)。

理想情况下(如果可能),DataGrid 将允许此委托或接口异步操作。 例如,委托或接口可能会返回TaskIAsyncOperation<TResult>而不是立即返回请求的值。

或者,如果 DataGrid 的操作类似于以下过程,则无需TaskIAsyncOperation<TResult>也可以支持异步:

  1. DataGrid 决定它需要检索行 ID 50001 中单元格/列 5 的值。或者,DataGrid 决定检索行 ID 50001 的所有列值。
  2. DataGrid 调用委托或接口实例或事件处理程序,通知应用程序 DataGrid 已请求加载指定列/行或整行的数据值。
  3. 应用程序异步检索请求的行数据。 例如,它可以异步执行 SQL 数据库查询。
  4. 应用程序完成检索请求的行数据。 该应用程序调用 DataGrid 中的一个方法,该方法将行数据提供给 DataGrid。
  5. DataGrid 显示行数据,或执行任何其他需要对数据执行的操作。

首先,哇!! 非常感谢所有贡献自己想法的人。 我在下面有一些具体的回应,但总的来说,我想说我节省了大量的这些评论,真的很高兴听到我们如何构建一个很棒的现代 DataGrid。 继续加油!

@Pinox非常感谢您的详细回复和屏幕截图。 你的愿望清单很棒(尤其是那些很酷的动画!) - 我同意 html 中的那些功能是一个很好的灵感点,很简单,但会大大提高生活质量。 肯定会保存此评论以备将来参考!

@verelpode@robloo@duke7553对 DataGrid 特定的事件是肯定的! 感谢大家对这些细节的投入。 当我们为触摸优先和各种输入设计时,绝对应该实现像这样的事件!

@dotMorten@jkewley@verelpode性能绝对是这个项目的主要动机之一,也是我们想要实现的主要改进之一,通过一个新的数据虚拟化故事和现代控件(如 ItemsRepeater)的使用。 一旦我们有更多细节,我们会及时通知你们所有人 - 但再次感谢你提供的这些细节。

@ Laz3rPanth3r,@robloo,@keeganatorr我们大声听你并清除约喜欢属于WPF和其他的UI框架的DataGrid中-我们肯定要考虑到这此刷新!

感谢您在 DataGrid 上所做的出色工作和反馈请求! 这里还有一些建议的增强功能。

需要更多的 DataGridColumn 子类

DataGridColumn的当前子类/实现是不够的。 我建议创建DataGridColumn的以下新子类:

| 提议的子类 | 说明 |
| :--- | :--- |
| DataGridIconColumn | 一个常见的要求是在列表的每一行中显示一个图标,因此我建议创建一个名为DataGridIconColumnDataGridColumn子类,它将检索到的单元格值类型转换为Windows.UI.Xaml.Controls.IconSource并呈现IconSource实例(在每个单元格中呈现不同的IconSource实例)。 |
| DataGridImageColumn | DataGridImageColumn应该与建议的DataGridIconColumn相同,除了它应该呈现Windows.UI.Xaml.Media.ImageSource而不是Windows.UI.Xaml.Controls.IconSource 。 |
| DataGridDateTimeColumn | 根据设置显示日期和/或时间。 将单元格值类型转换为System.DateTimeOffsetSystem.DateTime (均支持)并将其转换为要在单元格中显示的文本。 文本转换应由DataGridDateTimeColumn类中的格式设置/属性控制。 显然还必须支持按日期/时间排序。 |
| DataGridTimeSpanColumn | 将单元格值类型转换为System.TimeSpan并将其转换为要在单元格中显示的文本。 文本转换应由DataGridTimeSpanColumn类中的格式设置/属性控制。 显然排序也必须支持,它必须对TimeSpan实例而不是显示的文本进行排序。 |
| DataGridDataSizeColumn | 将单元格值类型转换为System.Int64UInt64Int32UInt32 (均支持)并将其转换为以字节为单位的大小(作为文本) 来显示。 例如,1572864 将显示为“1.5 MB”,因为 1572864/1024/1024 = 1.5。 文本转换应由DataGridDataSizeColumn类中的设置/属性控制。 必须使用原始整数值而不是显示的文本来执行排序。 |
| DataGridCustomColumn | 除了没有Windows.UI.Xaml.DataTemplate之外,这应该类似于预先存在的DataGridTemplateColumn Windows.UI.Xaml.DataTemplate 。 它应该调用委托/回调或事件来生成和/或更新显示的 GUI 元素子树。 |
| DataGridTextColumn | 已经存在,但请考虑添加允许应用程序覆盖对象到文本转换和排序比较功能的属性或事件。 我稍后会在我的消息中更详细地解释这一点。 |

DataGridCustomColumn应该是这样的:

public class DataGridCustomColumn : DataGridColumn
{
    public event EventHandler<DataGridDisplayingCellEventArgs> DisplayingCell;
}

public class DataGridDisplayingCellEventArgs : EventArgs
{
    public DataGridColumn Column { get; }
    public object CellValue { get; }
    public Windows.UI.Xaml.UIElement CellUIElement { get; set; } // settable
}

当事件DataGridCustomColumn.DisplayingCell被触发时,事件处理程序应该生成或更新它自己的UIElement子树以显示DataGridDisplayingCellEventArgs.CellValue ,并将属性DataGridDisplayingCellEventArgs.CellUIElementUIElement子树,然后DataGrid 将显示它。

下次 DataGrid 触发此事件时,DataGrid 应将属性DataGridDisplayingCellEventArgs.CellUIElement设置为先前由事件处理程序生成的UIElement实例,以允许事件处理程序重用/回收和更新相同的UIElement子树(可能在DataGridDisplayingCellEventArgs.CellValue具有不同的值)。 允许事件处理程序回收相同的UIElement子树或将属性DataGridDisplayingCellEventArgs.CellUIElement设置为新创建的UIElement子树。

还要考虑直接在基类DataGridColumn中创建新的DisplayingCell事件,而不是创建子类DataGridCustomColumn的可能性。 因此,事件DataGridColumn.DisplayingCell可以允许为DataGridColumn每个子类自定义或覆盖生成的UIElement DataGridColumn

在预先存在的DataGridTextColumn ,当前单元格值/对象通过调用System.Object.ToString转换为文本以显示。 请考虑进行委托/回调或事件,以允许应用程序覆盖此值到文本的转换。 还请考虑允许应用程序指定System.Collections.IComparer实例以覆盖排序行为的属性。

public class DataGridTextColumn : DataGridColumn
{
    public System.Collections.IComparer Comparer { get; set; }
    public DataGridCellValueToToStringConverter CellValueToToStringConverter { get; set; }
}

public delegate string DataGridCellValueToToStringConverter(object sourceObject);

或者,不是在DataGridTextColumn中创建Comparer属性,而是考虑在基类DataGridColumn直接创建Comparer属性的可能性,以便允许应用程序来控制DataGridColumn所有子类的排序行为。

同样, CellValueToToStringConverter属性也可以在基类DataGridColumn因为无论DataGridColumn的哪个子类,都可以将任何单元格值转换为文本。用来。 例如,将一行复制到剪贴板时,每个单元格值都可以转换为文本。 (文本和非文本格式可以同时放置在剪贴板中——应用程序通常这样做是为了增加与其他应用程序的兼容性。)

选择DataGridIconColumnDataGridImageColumn时重新排序:显然 DataGrid 无法对图标或图像进行排序,因此它可以使用以下任何一种解决方案:

  • 简单地禁止最终用户选择(排序)类型DataGridIconColumnDataGridImageColumn的列标题。
  • IconSource类中创建一个AlternativeText属性。 当DataGridIconColumn对行进行排序时,或者当它将单元格转换为剪贴板/副本的文本时,它将使用AlternativeText属性。
  • DataGridColumnDataGridIconColumn创建可设置的Comparer属性(类型System.Collections.IComparer )。

访问选定的行/项目

请考虑改进获取和设置所选行/项目的功能,因为当前功能不足。 目前这些属性存在:

public int SelectedIndex { get; set; }
public object SelectedItem { get; set; }
public System.Collections.IList SelectedItems { get; }

我发现有时候我需要访问所选行的DataGridRow实例,因此我希望可以在DataGrid中添加以下属性:

public DataGridRow SelectedRow { get; set; }
public IList<DataGridRow> SelectedRows { get; }

或者,如果上述内容太难实现,以下只读变体功能较弱,但仍然有帮助:

public DataGridRow SelectedRow { get; }
public IReadOnlyCollection<DataGridRow> SelectedRows { get; }

如果 DataGridRow 实例可以被回收,那么上述属性的文档应该警告返回的信息只是暂时有效,因此应该立即读取/使用它,而不是保留更长的时间。

此外,预先存在的SelectedIndex属性可以访问一个选定的索引,但是如何访问所有选定的项目呢? 因此,我建议创建以下SelectedIndexes属性:

public IList<int> SelectedIndexes { get; } // Suggestion.
public int SelectedIndex { get; set; } // Already exists.

我个人觉得“SelectedIndex”这个名字令人困惑,因为 DataGrid 经常与数据库结合使用,而术语“索引”在数据库中具有完全不同的含义,因此我建议按如下方式重命名属性,但我希望我的命名建议将被拒绝:

public IList<int> SelectedOrdinals { get; }
public int SelectedOrdinal { get; set; }

我还希望能够将指定的 DataGridRow 和/或 DataGridColumn 滚动到视图中。 目前这种方法存在:

public void ScrollIntoView(object item, DataGridColumn column);

我建议用这两种方法替换先前存在的ScrollIntoView方法:

public void ScrollIntoView(DataGridRow row, DataGridColumn column);
public void ScrollItemIntoView(object item, DataGridColumn column);

一键获取和设置排序顺序

当应用程序打开和关闭时,它们需要能够保存和恢复最终用户的 DataGrid 配置,包括排序顺序和其他设置。 排序顺序表示用户选择的列的列表。 请注意,这是一个列表,而不是单个列。 可以同时选择一个以上的列,即第一列进行排序,第二列进行排序,第三列进行排序等。

因此可以在 DataGrid 中创建以下属性,但实际上这只是第一个想法,并不理想:

public IReadOnlyList<DataGridColumn> SortOrder { get; set; }

以上是不理想的,因为它不支持在一次 hit 中保存和恢复每列的DataGridColumn.SortDirection 。 我意识到应用程序可以通过多个步骤来完成:

  1. 将建议的SortOrder属性设置为所选列的列表。
  2. 设置每个选定列的SortDirection属性(对每一列重复此步骤)。

这仍然有问题,因为它是多次点击,这意味着它会导致 DataGrid 的多次耗时。 当 DataGrid 被多次不必要地重新调用时,最终用户可能会注意到并遭受包含大量行的 DataGrid 的显着延迟。 为了消除这个问题,我建议使用以下解决方案,允许应用程序在一次点击中恢复完整的排序顺序,并且不会超过一个单一的手段。

public class DataGrid
{
    public IReadOnlyList<DataGridColumnAndDirection> SortOrder { get; set; }
    ...
}

public struct DataGridColumnAndDirection
{
    public readonly DataGridColumn Column;
    public readonly DataGridSortDirection SortDirection;
    public DataGridColumnAndDirection(DataGridColumn, DataGridSortDirection) { ... }
}

注意我在上面故意写了IReadOnlyList<DataGridColumnAndDirection>而不是IList<DataGridColumnAndDirection>因为应用程序不应该能够修改SortOrder属性返回的列表。 应用程序不应修改列表,而应将SortOrder属性设置为 DataGrid 将复制并用于完全替换整个排序顺序列表的列表。 因此,它可以一击即中,避免多个昂贵的度假村。

DataGrid.SortOrder设置为新列表时,DataGrid 还会在新的SortOrder列表中的每一列中设置相应的DataGridColumn.SortDirection属性,但不会导致多个度假村。 因此DataGrid.SortOrder[i].SortDirection等价于DataGridColumn.SortDirection

一键获取和设置显示的列顺序

当应用程序打开和关闭时,它们需要能够保存和恢复最终用户对列的排序,最好是一次性完成。 我知道预先存在的属性DataGridColumn.DisplayIndex是可设置的,因此理论上应用程序可以通过遍历DataGrid.Columns所有列并设置每个列的DisplayIndex来恢复最终用户的配置,但是这可能会导致错误。 例如,当应用程序需要将一列的DisplayIndex临时设置为另一列的DisplayIndex时, DisplayIndex可能会失败或以意外方式运行。 此外,如果它不是一次命中,那么它可能会触发多次昂贵的重绘和/或重新计算。

因此我建议在 DataGrid 中创建一个ColumnDisplayOrder属性:

public IReadOnlyList<DataGridColumn> ColumnDisplayOrder { get; set; }

与我之前提到的SortOrderColumnDisplayOrder故意是IReadOnlyList<DataGridColumn>而不是IList<DataGridColumn>因为它应该一次运行。
DataGrid.ColumnDisplayOrder设置为新列表时,DataGrid 将更新每列的DataGridColumn.DisplayIndex以进行匹配。

允许最终用户隐藏/显示列

与预先存在的属性DataGridColumn.CanUserReorder等一致,我建议在DataGridColumn创建一个CanUserChangeVisibility属性。 当DataGridColumn.CanUserChangeVisibility为真时,最终用户将能够对DataGridColumn.Visibility属性进行更改。

支持运行时动态生成的 GUI 元素

无需使用DataGrid.RowDetailsTemplate ( Windows.UI.Xaml.DataTemplate ) 即可生成行详细信息 GUI。 为了实现这一点,需要在 API 中加入一些想法,但这是我的第一个想法:也许通过改变属性DataGridRowDetailsEventArgs.DetailsElement通过预先存在的事件DataGrid.LoadingRow来实现可设置,以便事件处理程序可以自行生成(或更新)UIElement,并通过设置DetailsElement属性将其提供给 DataGrid。

强制使用Windows.UI.Xaml.DataTemplate是一个问题:虽然模板是一个很好的特性,但模板概念需要预先创建的、由开发人员编写的不变的 XAML 片段/文档。 因此,当应用程序需要在运行时动态生成 GUI 时,模板是一个问题。 因此,我希望上述DataTemplate替代品。

向内和向外拖放行

我建议能够选择启用行的传出拖放。 DataGrid 将实现拖动而不是放置。 当放置发生时,DataGrid 将触发一个事件,应用程序响应该事件以便在将行放置到 DataGrid 之外时执行所需的操作。

还能够选择性地启用行或项目/对象的传入拖放。 DataGrid 将接受传入的拖放,但不实现拖放。 当行/项目/对象被放置时,DataGrid 将触发一个事件,当行被放置在 DataGrid 中时,应用程序响应该事件以执行所需的操作。

单个细胞背景

我们有一个客户的功能请求,他希望在特定时间(例如,当我们的应用程序检测到更改或重要值或危险值超过安全限制等时)对单个单元格进行 hilited(通过更改单元格背景颜色/画笔)。

因此,我可以提出DataGridCell.Background属性(类型Brush ),但我认为这种做法可能有缺陷,因为 DataGrid 回收DataGridCell实例,不是吗? 所以我想通过设置DataGridCell.Background属性来限制单个单元格将是一个不可靠的解决方案。

更好的方法可能是通过我在之前的消息中提出的事件DataGridColumn.DisplayingCell 。 事件处理程序可以在DataGridDisplayingCellEventArgs设置CellBackgroundBrush属性。

Dumb-down DataGrid 对数据(单元格值)的检索

我知道“愚蠢”听起来很糟糕,但实际上,如果 DataGrid 在数据检索(检索要由 DataGrid 显示的单元格值)领域变得愚蠢,我会喜欢它。

目前,DataGrid 尝试通过其属性DataGrid.ItemsSource加上数据绑定技术(属性DataGridBoundColumn.Binding )和诸如System.ComponentModel.INotifyPropertyChanged接口以一种方便的自动方式执行数据检索。

是的,数据绑定是一个方便的功能,但实际上我更喜欢让 DataGrid 在那个部门做_少_! 几个 Microsoft 组件实际上给我带来了很大的困难,因为它们试图变得聪明但实际上最终太聪明了。 总的来说,如果这些组件不再试图变得如此智能/自动化/方便,我实际上会遇到更少的困难和更少的工作。 在设计自动行为时,我发现值得牢记自动行为听起来很棒但有可能适得其反。

_“就让我自己做吧。”_
有时,最好的解决方案是简单地允许应用程序自行执行任务,而不是在诸如 DataGrid 之类的组件内“自动”尝试并失败。 我希望 DataGrid 可以让我自己完全执行数据检索,而不是尝试通过属性DataGridBoundColumn.BindingDataGrid.ItemsSource自动检索数据。

理想情况下,我想消除使用属性DataGrid.ItemsSource来提供物品的要求。 @dotMorten提到了一百万行。 当前 DataGrid 强制应用程序设置DataGrid.ItemsSource ,但创建包含一百万个项目的列表对象是不切实际的。 因此,我希望 DataGrid 在数据检索部门不再聪明,而是让我自己完全执行数据检索,而不使用DataGridBoundColumn.BindingDataGrid.ItemsSource

@anawishnoff写道:

性能绝对是这个项目的主要动机之一,也是我们想要实现的主要改进之一,通过一个新的数据虚拟化故事和现代控件的使用,如 ItemsRepeater。

我看到你说新的数据虚拟化故事会提高性能,这是个好消息,但它还会消除使用属性DataGridBoundColumn.Binding来提供 DataGrid 显示的单元格值的要求吗?

如果整个数据检索工作外包给使用 DataGrid 的应用程序,则该应用程序可以完全灵活地以它需要的任何方式执行数据检索。 这将启用许多不同的数据检索方案,包括@dotMorten提到的百万行。 废话少说,请 :smile:

WPF DataGrid 中一些不必要的功能?

DataGrid 的 WPF 版本有一些看起来不必要或不切实际的功能,这些功能可以在 WinUI DataGrid 中跳过,但我预计有些人可能对这些功能有不同的看法。

如果 WinUI DataGrid 放弃最终用户能够在 DataGrid 内内联/直接编辑单元格值的功能,有多少人会提出异议? 在我们的例子中,在我们使用 DataGrid 的每个地方,我们总是将DataGrid.IsReadOnly为 true 以禁用内联/直接编辑功能。 我们允许用户在单独的窗格或面板中或在 RowDetails ( DataGrid.RowDetailsTemplate ) 中编辑选定的行,但不能直接在 DataGrid 内部进行编辑。

似乎 WinUI DataGrid 已经朝着取消对内联/直接编辑的支持的方向发展,因为 WPF DataGrid 有CanUserAddRowsCanUserDeleteRows但这些属性在 WinUI DataGrid 中不再存在。 为什么不完全放弃内联/直接编辑功能? 有多少人反对这个想法?

单个单元格选择:WPF DataGrid 有一个SelectionUnit属性,您可以将其设置为CellFullRowCellOrRowHeader 。 在我们的例子中,我们总是将它设置为FullRow并且从未发现需要将它设置为Cell 。 但是我看到这里有人已经请求了单细胞选择模式。 我的问题是单元格选择模式是常见的还是罕见的请求。

另一方面,当用户将行/单元格复制到剪贴板时,单个单元格选择可能很有用。 它将允许用户将单个单元格(或几个连续的单元格)复制到剪贴板,而不是复制整行。 但是我不确定这个功能是否真的有价值。

| WPF 中的可疑功能 | 评论 |
| :--- | :--- |
| DataGrid.IsReadOnly | 也许真的不需要将 IsReadOnly 设置为 false? |
| DataGrid.CanUserAddRows | WinUI DataGrid 中不存在。 已经放弃,或者可能尚未实施(我不知道计划)。 |
| DataGrid.CanUserDeleteRows | WinUI DataGrid 中不存在。 已经放弃,或者可能尚未实施(我不知道计划)。 |
| DataGrid.SelectionUnit | WinUI DataGrid 中不存在。 |

哇,这里令人难以置信的讨论。 ❤️

我也同意 WPF DataGrid API。 WPF DataGrid 确实是我想要的 WinUI 3.0 的 DataGrid。

但即使是 WPF DataGrid 也缺乏一些功能。 过去,我的大多数客户使用更强大的 3rd 方 DataGrid 来获得这些功能:

  • 列标题中的过滤器
  • DataGrid 顶部的完整过滤器行
  • 强大的分层数据显示。 一些 3rd 方 DataGrids 真的像带有嵌套 DataGrids 的强大 TreeView 一样工作。 虽然 WPF DataGrid 允许构建类似的东西,但它不支持开箱即用
  • 支持不同的数据类型。 例如一个 DateTime 列。 在 WPF 的 DataGrid 中,您必须使用 DataGridTemplateColumn

但无论如何,无论你做什么,我认为构建 DataGrid 是对 WinUI 3.0 的有力声明和承诺。 对于 LOB 应用程序,您不能认真对待不包含内置 DataGrid 的 UI 框架。 很高兴看到这项为 WinUI 所做的投资!

@thomasclaudiushuber

对于 LOB 应用程序,您不能认真对待不包含内置 DataGrid 的 UI 框架。 很高兴看到这项为 WinUI 所做的投资!

同意! 在我们的例子中,DataGrid 是一个至关重要的组件,我们在多个地方使用它并且离不开它。

强大的分层数据显示。 一些 3rd 方 DataGrids 真的像带有嵌套 DataGrids 的强大 TreeView 一样工作。

我对这个话题感到厌烦,因为 - 和你一样 - 我会发现分层 DataGrid 在某些情况下很有用,但我担心的是,如果 DataGrid 确实实现了分层功能,那么它可能会变得过于复杂和困难,并且DataGrid 很可能会大幅延迟。 由于使新功能与分层和非分层功能兼容的复杂性,新功能将难以添加。

为了消除上述复杂性/延迟问题,我建议使用以下解决方案:创建一个名为HierarchicalDataGrid的单独类,该类在内部使用/包装DataGrid的实例。 或者HierarchicalDataGrid可以公开继承DataGrid但我怀疑这种继承是不切实际的,因此我更愿意建议HierarchicalDataGrid继承Control并在内部有一个私有字段输入DataGrid 。 因此,分层功能将在HierarchicalDataGrid层中实现,该层指示内部非分层DataGrid实例。

上述解决方案的主要优点是,可以提供所需的分层特性 _without_ 陷入困境DataGrid ,而不会使DataGrid变得如此复杂,以至于变得难以管理和开发缓慢。

支持不同的数据类型。 例如一个 DateTime 列。

我同意。 查看我在之前的消息中提出的DataGridDateTimeColumnDataGridTimeSpanColumn

@皮诺克斯

轻松过滤整个页面

@thomasclaudiushuber

列标题中的过滤器; DataGrid 顶部的完整过滤器行;

过滤器非常适合帮助最终用户快速找到一行或多行,而不是当前被迫手动查看大量行以找到他们要查找的内容的情况。

但是用户过滤文本与非文本列匹配的问题呢? 表示DataGridTextColumn以外的列,例如用DataGridTemplateColumn等过滤? 我建议使用类似于以下解决方案的方法解决此问题,该解决方案使DataGridColumn (和子类)能够将单元格值转换为关键字以用于搜索/过滤/匹配。

public delegate void DataGridCellValueToKeywordsConverter(object cellValue, ICollection<string> outputKeywords);

public class DataGridColumn
{
    ...
    public DataGridCellValueToKeywordsConverter CellValueToKeywordsConverter { get; set; }

    /// <param name="cellValue">The input/source value of the cell, to be converted to keywords.</param>
    /// <param name="outputKeywords">A collection that the method will add the keywords to.  The method invokes ICollection.Add for each keyword.</param>
    public virtual void ConvertCellValueToKeywords(object cellValue, ICollection<string> outputKeywords)
    {
        // Subclasses can override this method.  The default behavior is to invoke the delegate to do the job.
        DataGridCellValueToKeywordsConverter d = this.CellValueToKeywordsConverter;
        if (!(d is null)) d(cellValue, outputKeywords);
    }
}

以下是如何使用ConvertCellValueToKeywords方法的示例:

void TestKeywords(DataGridColumn column)
{
    var keywords = new System.Collections.Generic.HashSet<string>();
    foreach (object cellValue in someCellValueList)
    {
        keywords.Clear();
        column.ConvertCellValueToKeywords(cellValue, keywords);
        CheckIfFilterTextMatchesAnyKeyword(keywords);
    }
}

或者,可以将单元格值转换为单个字符串而不是关键字集合,但是我建议使用关键字集合的原因是关键字可以使用高速运行的搜索算法,即使行数为很大。

从excel轻松复制过去
现在无法使用 ctrl+v 将 Excel 单元格内容复制到数据网格。 现在它将所有单元格内容复制到数据网格中的一个单元格。

请通过将 SelectedItems 作为依赖属性来提供适当的多选定项支持,以允许在管理选定行时使用数据绑定。

@verelpode我可以看到单个单元格选择对任何电子表格类型的应用程序

@anawishnoff我觉得@ Laz3rPanth3r会同意这对夫妻的问题,在这里这里从工具包,能够轻松,方便地提取数据到DataGrid中的一个重要特征。 您应该能够通过绑定到列表中的一组对象或 expando 对象来引导网格。 如果它可以智能地为数字和字符串以及基本数据类型选择列,那就太好了。 在自定义除此之外的各个列之后,开发人员始终可以做更多的工作。

我可以看到单个单元格选择对任何电子表格类型的应用程序都很有用,不是吗?

在电子表格中,列标题以字母表中的升序字母命名,A、B、C、D...,并且每一列的类型都相同,就好像每一列都使用DataGridTextColumn而没有其他列type 是必需的,列名也不是真正需要的,因为它们是从字母表中自动生成的。
DataGrid 和电子表格之间的另一个区别是,当您单击任何列标题时,电子表格不会对行进行排序。

我的观点是,DataGrid 和电子表格之间仅存在表面相似性(主要是视觉相似性)。 DataGrid 并不像电子表格那样真正运行。 DataGrid 的单元格数据检索技术也不太适合电子表格。

我喜欢 DataGrid,但如果我试图用它来实现电子表格,它的功能会很差。 我不认为 DataGrid 是任何想要实现电子表格的人的正确选择。

与电子表格相比,DataGrid 的现有设计与 SQL 数据库的一致性要好得多,如果有人试图声称数据库“只是一个电子表格”,SQL 数据库开发人员会大声喊叫。

@verelpode您的贡献是如此详细和深思熟虑,非常感谢您所做的一切! 我想谈谈绑定数据源/DataGrid 的 ItemsSource 属性的想法,正如你提到的,@michael-hawker 也是如此。

目前,DataGrid 强制应用程序设置 DataGrid.ItemsSource,但创建包含一百万个项目的列表对象是不切实际的。 因此,我希望 DataGrid 在数据检索部门不再智能,而是让我自己完全执行数据检索,而不使用 DataGridBoundColumn.Binding 和 DataGrid.ItemsSource。

这很有趣,我想更深入地研究它,因为我们对性能非常感兴趣。 您具体要寻找什么样的数据情况/场景? 您想将 DataGrid 直接连接到 SQL 查询结果、数据库或类似的东西吗?

@khoshroomahdi通过复制和粘贴,您的意思是您想将 excel 单元格复制到正在运行的应用程序中的 DataGrid 中,并以这种方式填充? 这是一个有趣的用例,我想听听更多。

@alexyak ,你

@anawishnoff是的。
我在 Excel 单元格中有一些数据,想在正在运行的应用程序中复制它们。

对于非数据绑定的场景,我们应该看看我多年前写的WinForms DataGridView控件是如何支持虚拟模式的: https :

目前,DataGrid 强制应用程序设置 DataGrid.ItemsSource,但创建包含一百万个项目的列表对象是不切实际的。 因此,我希望 DataGrid 在数据检索部门不再智能,而是让我自己完全执行数据检索,而不使用 DataGridBoundColumn.Binding 和 DataGrid.ItemsSource。

我同意那也很好。 我在想像 ListBox 这样的东西,您可以在其中手动添加项目或设置 ItemsSource。 也就是说,过去我只是生成一个新的 DataTable 表示完整数据库的部分视图来实现分页(这是一个很好的用例)。 然后可以将该 DataTable 的视图设置为 ItemsSource。 所以虽然我绝对认为这很好,但它似乎不是高性能的必需品。

关于将控件或多或少变成 Excel(r) 子集的所有评论,我认为 DataGrid 开箱即用应该支持单元格选择和每个单元格的编辑。 但是,诸如在外部应用程序之间复制/粘贴之类的事情应该由开发人员处理。

@alexyak关于您要求使 SelectedItems 成为真实的、可绑定的 DependencyProperty 这对于恢复状态也很好(到目前为止我的大多数功能请求都是恢复视图状态)。 我认为这是一个框架范围的问题,因为我知道的任何 WinUI/UWP 控件都不支持它。 这应该是一个通用的功能请求。 请参阅此处的讨论

@anawishnoff写道:

您的贡献是如此详细和深思熟虑,非常感谢您所做的一切!

谢谢,我很高兴听到我的贡献有助于使 DataGrid 变得更好:)

您具体要寻找什么样的数据情况/场景? 您想将 DataGrid 直接连接到 SQL 查询结果、数据库或类似的东西吗?

那还是太聪明了。 这种智能行为可防止不同的应用程序以不同的方式执行数据检索。 不同的应用程序有很大不同的情况,因此不同应用程序的“最佳”数据检索系统是不同的——不存在单一的“最佳”。 例如,一些应用程序永远不会显示超过几百行,而其他一些应用程序可能会像@dotMorten提到的那样处理一百万行,因此一种鞋码并不适合所有人。

我建议真的把它降到这个水平:

  1. DataGrid 决定它需要显示(或以其他方式使用)外部数据存储系统中第 9001 行第 5 列中存在的值。
  2. DataGrid 通知应用程序它需要第 9001 行第 5 列的值。
  3. 应用检索第 9001 行第 5 列的值。这可能涉及异步 SQL 查询、异步 C# 任务或任何其他数据系统。 理想情况下,DataGrid 应该允许这一步是异步的。
  4. 该应用程序通知 DataGrid 已完成检索第 9001 行第 5 列的值。该应用程序将此值提供给 DataGrid。
  5. DataGrid 以它需要的任何方式使用该值,例如显示第 1 步中提到的值。

@RBrid写道:

对于非数据绑定的场景,我们应该看看我多年前写的WinForms DataGridView控件是如何支持虚拟模式的:

对对对! 我从未使用过 WinForms DataGridView,但我现在只是阅读了文档,我相信您已经一针见血了。 您链接到
_“虚拟模式设计用于非常大的数据存储。”_

我看到 WinForms DataGridViewCellValueEventArgs包含以下属性:

public int RowIndex { get; }      // DataGrid sets RowIndex.
public int ColumnIndex { get; }   // DataGrid sets ColumnIndex.
public object Value { get; set; } // The app sets Value.

这很好,除了理想情况下它应该更新以支持现代 C# asyncawait关键字,或 UWP 等效项 ( IAsyncOperation<TResult> ),或者任何类型的时间延迟在请求单元格值的 DataGrid 和将单元格值传递给 DataGrid 的应用程序之间。 因此要更新它以支持异步,请执行以下操作:

  1. 保持事件CellValueNeeded
  2. 删除属性DataGridViewCellValueEventArgs.Value
  3. 在 DataGrid 中创建一个名为SupplyCellValue ,应用程序将调用该方法,而不是立即/同步设置属性DataGridViewCellValueEventArgs.Value

SupplyCellValue方法可以这样定义:

class DataGrid
{
    public void SupplyCellValue(int rowIndex, int columnIndex, object value);
    // Alternatively:
    public void SupplyCellValue(int rowIndex, DataGridColumn column, object value);
}

因此在运行时过程是:

  1. DataGrid 决定它需要显示(或以其他方式使用)外部数据存储系统中第 9001 行第 5 列中存在的值。
  2. DataGrid 触发事件CellValueNeeded并将DataGridViewCellValueEventArgs.RowIndex为 9001,将DataGridViewCellValueEventArgs.ColumnIndex为 5。
  3. 事件处理程序(应用程序)开始运行一个异步任务,该任务将检索第 9001 行第 5 列的值。
  4. 当异步任务完成运行时,意味着当应用程序检索到值时,应用程序调用方法DataGrid.SupplyCellValue

这种简化的技术比DataGridBoundColumn.BindingDataGrid.ItemsSource的智能自动化技术强大和灵活。

@alexyak ,你

我们需要一个合适的双向数据绑定来让视图模型管理多个选择

@verelpode ,我们在更旧的 Win32 ComCtl32 控件之后对 WinForms DataGridView 模型进行了建模。 特别是,我正在考虑列表视图控件如何在虚拟模式下使用 LVN_GETDISPINFO 消息(请参阅 https://docs.microsoft.com/en-us/windows/win32/controls/list-view-controls-overview #handling-virtual-list-view-control-notification-codes 和 https://docs.microsoft.com/en-us/windows/win32/controls/lvn-getdispinfo)。 90 年代的老东西。

无论如何,我相信处理异步数据检索方面的方式是通过“延迟事件”。
WinUI 控件已经使用了两次延迟事件:

runtimeclass RefreshRequestedEventArgs
{
    Windows.Foundation.Deferral GetDeferral();
}

runtimeclass TeachingTipClosingEventArgs
{
    TeachingTipCloseReason Reason{ get; };
    Boolean Cancel;
    Windows.Foundation.Deferral GetDeferral();
}

这是新 DataGrid 的 CellValueNeeded 事件想要采用的模式。 它允许事件处理程序异步提供数据并在完成时通知控件。 请参阅https://docs.microsoft.com/en-us/uwp/api/windows.foundation.deferral。

@RBrid
关于GetDeferral()成为新标准模式的好处。 在CellValueNeeded这种特殊情况下,使用Deferral似乎比其他情况/事件要困难得多。 如果我错了,请纠正我,但我认为在这种特殊情况下使用GetDeferral()的问题是GetDeferral()每次调用时都会创建一个新对象,这会导致过度对于潜在大量行的每一行的每个单元格重复大量的对象创建和清理。 我还没有看到各种GetDeferral()实现的源代码,因此我可能会误会这一点。

换句话说,除非Deferral支持回收或以其他方式使GetDeferral()更有效率,否则它仍然太聪明了。 我使用SupplyCellValue方法的简化建议避免了为每个适用行的每个单元格创建、完成和处理新的Deferral实例的开销。

  1. GetDeferral()
  2. 延期完成
  3. 延期处置
  4. 多次重复上述步骤。

检索单元格值的任务并不是唯一可能外包给应用程序的数据管理任务。 排序也可能外包。 因此,考虑考虑接口而不是单个事件CellValueNeeded可能是值得的。 应用程序将以实现特定接口的对象的形式为 DataGrid 提供数据管理模块。 DataGrid 将调用此接口以检索单元格值,但也可能执行其他任务,例如排序。

为了支持@dotMorten提到的百万行,CellValueNeeded并不能解决用户单击列标题并且 DataGrid 尝试对一百万行进行排序时出现的另一个问题。 因此,细胞检索和排序可以通过上述模块/接口外包给应用程序。

如果应用程序不向 DataGrid 提供任何数据管理模块/对象,那么理想情况下 DataGrid 将使用默认数据管理模块。 因此,DataGrid 中所有现有的数据绑定代码都将从 DataGrid 移出并移到一个单独的新类中——该类通过使用DataGridBoundColumn.Binding等来实现默认数据管理模块。

即当排序也外包给应用程序或其数据管理模块时,这为支持一百万行的各种解决方案打开了大门,例如编写一个数据管理模块来指示 SQL 服务器执行排序,而不是尝试 -并且在用户单击列标题开始排序后的 10 或 20 小时内未能对 DataGrid 中的一百万行进行排序。

@verelpode ,是的,这是一个有效的问题。 我希望 DataGrid 拥有一个可回收的 Windows.Foundation.Deferral 对象池。 我们需要确认可行性和性能。

依赖于 Windows Community Toolkit DataGrid,它具有 Row Details 作为一个特性(尽管存在严重的性能错误但有一个解决方法),我们真的希望这个新的 datagrid 也将它作为一个特性 - 使用相同的选项同时具有多个行详细信息。 将它用于服务器到客户端的流数据场景。

一百万行与分页GUI, @robloo写道:

我同意 [支持一百万行] 也会很好。 .... 也就是说,过去我只是生成一个新的 DataTable 代表完整数据库的部分视图来实现分页(这是一个很好的用例)。 然后可以将该 DataTable 的视图设置为 ItemsSource。 所以虽然我绝对认为这很好,但它似乎不是高性能的必需品。

分页是一种有用的技术,值得一提,但它有很大的缺点:它使 DataGrid 的排序功能实际上毫无用处。 同样对于下一版本的 DataGrid 中的过滤功能。 分页使排序和过滤变得毫无用处,或者至少没有多大用处。

例如,假设有 2 或 3 列是日期列,并且用户想要查看第二个日期列中具有最近(或最早)日期的行。 因此,用户单击第二个日期列标题以按该列对 DataGrid 进行排序,并且还单击以将排序方向从降序更改为升序,反之亦然。 如果没有使用分页,或者如果总行数小到不超过单页,这很有效,但如果存在多页,则会中断。

用户需要在所有行中找到最近(或最早)的日期,但分页 DataGrid GUI 仅显示当前页面中的最近(或最早)日期,而不是所有行,因此分页实际上可以进行排序(和过滤)无用。

这就提出了哪些行落在哪个页面上的问题。 答案是,当页面/行是通过不使用ORDER BY的 SQL SELECT查询获得时,每个页面通常包含行的一个几乎随机的子集。 (我的意思是从用户的角度来看是随机的,而不是真正的随机。)

伪随机对最终用户没有帮助。 为了消除这种有问题的随机性,我们可以考虑使用 SQL ORDER BY (连同ASCDESC关键字来控制排序方向),然后是的页面不是更长的随机性,但它仍然被破坏,因为ORDER BY这种用法总是按相同的列和相同的排序方向排序,这意味着排序顺序经常与最终用户单击列选择的排序顺序不同DataGrid 中的标头。

要修复它,每次用户单击不同的列标题时,您都需要使用不同的 SQL 查询。 SQL ORDER BY ... ASC/DESC需要与 DataGrid 的最终用户选择的任何排序顺序保持相同。 DataGrid 目前不支持此功能。

建议的解决方案在我之前的消息中:我建议 DataGrid 应该允许将排序外包给应用程序(或“数据管理模块”)。 这个想法将使应用程序(或“数据管理模块”)能够在最终用户通过单击列标题等更改 DataGrid 的排序顺序时更改 SQL ORDER BY ... ASC/DESC

在事件参数中为预先存在的事件DataGrid.Sorting一个可设置的属性也可能是值得的,该属性允许应用程序(事件处理程序)取消排序并接管。 理想情况下,事件参数还将指定排序顺序更改是通过编程方式请求还是最终用户单击列标题等请求。在这种情况下,将事件DataGrid.Sorting重命名为不那么模棱两可的内容可能也有帮助因为目前Sorting活动的意图和目的尚不清楚。 另请参阅我的另一条消息中提议的

依赖于具有 Row 的 Windows Community Toolkit DataGrid
细节作为一个功能(虽然有严重的性能错误但有一个解决方法),我们会
真的很喜欢这个新的数据网格也有它作为一个功能 - 具有相同的选项
同时多行详细信息。 将它用于服务器到客户端的流数据场景。

链接到行详细信息性能问题: https :
重现: https :

一个很好的起点是查看您的合作伙伴 Telerik 及其 RadDataGrid(UWP 开源)。 我和我的一位客户一起使用了它,它实际上运行良好。 它速度极快且用途广泛。 唯一困难的是他们的代码,如果对架构没有很好的理解,就无法从他们的引擎中修改任何内容。

我希望新的 DataGrid 与 Telerik 一样高效。

syncfusion 网格功能很棒,但它们不是 mvvm 友好的。 所以你可以做得更好。

大家好! 让我们继续这个对话。 您对当前存在的 DataGrid 文档有何看法?

这是指向所有其他相关页面的主文档页面的链接。

如果我们创建一个新的 DataGrid,我们希望确保它附带的文档是一流的、易于理解的,并且解决了对我们的开发人员很重要的所有问题和场景。

_您希望我们有哪些主题? 有哪些话题可以澄清?_

大家好! 让我们继续这个对话。 您对当前存在的 DataGrid 文档有何看法?

这是指向所有其他相关页面的主文档页面的链接。

如果我们创建一个新的 DataGrid,我们希望确保它附带的文档是一流的、易于理解的,并且解决了对我们的开发人员很重要的所有问题和场景。

_您希望我们有哪些主题? 有哪些话题可以澄清?_

显示典型 DataGrid 设置以及 xaml 和创建它们的代码的图像会很有用。

显示典型 DataGrid 设置以及 xaml 和创建它们的代码的图像会很有用。

@mdtauk是否有您认为“典型”的特定 DataGrid 设置,或者您始终认为 DataGrid 是最佳选择的用例?

显示典型 DataGrid 设置以及 xaml 和创建它们的代码的图像会很有用。

@mdtauk是否有您认为“典型”的特定 DataGrid 设置,或者您始终认为 DataGrid 是最佳选择的用例?

我认为对于 WinUI 3.0 时间框架,显示常见的 WPF、Win32 数据网格/图标视图方案。 以及 Microsoft 认为的 Fluent/Modern DataGrid UI 设计。

也就是说,如果控件背后的想法是鼓励从旧 UI 迁移到 WinUI 3

@anawishnoff我认为我们从工具包中提出的一些问题是关于人们正在寻找更多这些场景的文档:

  • 主题化/重新模板化/对齐
  • 数据绑定(一般和 XAML)
  • 事件/选择处理/外壳
  • 编辑行为(尤其是点击编辑)
  • 多分页(应该与 #60 和 #268 搭配得很好)

    • 加载数据时加载动画协调

  • 复制/粘贴/格式化
  • 不同的列数据类型(和自定义的)(例如枚举)
  • 上下文菜单
  • 无障碍

我注意到现有的 Toolkit DataGrid 需要一个 IEnumerable 作为它的 ItemsSource 属性。 虽然这看起来是一个合乎逻辑的决定,但它使得将 Windows.Storage.BulkAccess.FileInformationFactory.GetVirtualizedItemsVector() 返回的对象设置为该属性是不可能的。 (除非有一种方法可以转换返回的对象)此外,其他控件(如 ListView 和 GridView)支持将它们的 ItemsSource 属性设置为对象类型的值。 我不确定,但支持这一点可能会在存储操作期间提供更灵敏的用户界面。

@mdtauk是否有您认为“典型”的特定 DataGrid 设置,或者您始终认为 DataGrid 是最佳选择的用例?

我认为对于 WinUI 3.0 时间框架,显示常见的 WPF、Win32 数据网格/图标视图方案。 以及 Microsoft 认为的 Fluent/Modern DataGrid UI 设计。

也就是说,如果控件背后的想法是鼓励从旧 UI 迁移到 WinUI 3

Win32 示例(文件资源管理器)
image

WPF 示例
image

织物网络示例
image

UWP 示例
image

@mdtauk感谢您提供这些屏幕截图! 我绝对认为突出显示在以前版本的控件中起作用的关键元素并记录如何使用新控件实现这些元素非常重要。

@michael-hawker 很棒。 我已经看到其中的一些主题已在此线程上多次提出,因此这些绝对是一个很好的起点。

@duke7553我不是 100% 确定是否有解决方案,或者支持对象类型是否明智。 也许@RBrid可以

@anawishnoff & @duke7553 ,我将在新的 WinUI ItemsRepeater 控件之上构建新的 DataGrid 控件。 该控件将其 ItemsSource 作为对象公开:
Object ItemsSource { get; set; };

希望它像 Telerik 一样支持 CellDecorationStyleSelector。

@anawishnoff

我们有兴趣将其升级为本机 WinUI 控件

嗯,当您说“毕业”时,是否包括将其降级为 C++? 目前 WinUI 的 DataGrid 是用 C# 编写的。 我希望“毕业”并不意味着“降级”。 重要的是,WinUI 需要达到这样的程度,即 WinUI 团队可以说 WinUI 在各方面都比 WPF 更重要,但这个目标已经非常晚了。 如果时间/资源浪费在不必要的代码降级(例如 DataGrid 从 C# 到 C++)上,那么这个目标将变得更加迟到。

虽然原来用C++写WinRT/UWP/WinUI是有理由的,可惜那个理由没有结果,谷歌/Android占据了智能手机的大部分市场份额,所以原来用C++的理由已经不适用了(很容易事后说,但没那么容易早说)。 如果WinUI从一开始就是用C#写的,那么3年前就可以实现优于WPF的目标,但是现在8年了还没有实现,谁也无法准确说出这个目标什么时候能实现。 希望优于 WPF 的目标和 WinUI DataGrid 的“毕业”目标不会因向旧的、效率较低的编程语言的不必要转换而延迟。

我偏向于 C++,因为我在 C# 出现之前就开始使用 C++ 进行编程,人们更喜欢坚持他们最初学到的东西,并深情地记住_“过去的美好时光”_。 尽管我偏向于 C++,但我停止编写 C++,我认为 DataGrid 不应该降级为 C++ 并延迟。 将其保留为 C# 并专注于更重要的事情,例如在此问题中进行人们建议的各种改进,并在达到 10 年之前实现优于 WPF 的目标。

我喜欢 WinUI 的许多方面,欣赏其中的许多巧妙改进,我为 WinUI 编写应用程序代码,但您想知道真相吗? 事实是,遗憾的是,我还没有向用户发布任何WinUI 应用程序。 发布给用户的软件是用 WPF 编写的,用户并不关心,因为该软件运行良好并且包括 GUI 现代化。 虽然我已经为 WinUI 编写了一大堆应用程序代码,但这些都是准备、计划、测试、等待,而不是用户实际使用。 希望明年第一个 WinUI 组件将发布给用户,但我会比他们更欣赏这种转换。 如果一切按计划进行,用户几乎不会注意到切换。

在微软看来,WinRT/UWP 是发布质量的软件,从 2012 年开始向用户发布,但在我看来,UWP 仍然是一个大实验。 对我来说, UWP(包括 WinUI)都是我多年来一直在玩

在UWP的最初几年,每年我都在想:_"errr...我会等到明年。WPF中还有太多东西在UWP中缺少。明年肯定会更好。"_
然后第二年来了,我重复了同样的想法。 然后第二年来了,我重复了同样的想法。 希望今年是说这句话的最后一年,或者至少这是我的意图。

WinUI 无法承受更多的延迟。 将 WinUI 的 DataGrid 保留为 C# 代码。 开始使用 C# 编写更多 WinUI 代码以提高工作效率。 现在已经 8 年了,Android 已经占据了巨大的市场份额。 这是一个严重的情况。

顺便说一句,当我说 UWP 仍然是 beta 版本时,我实际上是很好/慷慨的,因为从技术上讲,UWP 匹配 alpha 版本的定义,而不是 beta。 要成为真正的 beta 版本,它需要功能完备,但 UWP 尚未达到功能完备的状态,因此 UWP 仍为 alpha。 比如维基百科的“软件发布生命周期”一文说:

“测试阶段通常在软件功能完成但可能包含许多已知或未知错误时开始。”
“Alpha 软件可能不包含为最终版本计划的所有功能。”

维基百科对“功能完备”的定义如下:

“一个软件的功能完整版本已实现其所有计划或主要功能,但由于错误、性能或稳定性问题尚未最终确定。这发生在开发的 alpha 测试结束时。”

将 UWP 描述为功能完备是不合理的,因为如果它真的功能完备,那么 UWP 必须具有 Windows '95 的所有功能以及更多功能,但事实并非如此——UWP 在所有方面还没有超过 Windows 95 . Windows 95 于 25 年前发布。 在 7-8 年前发布 UWP/WinRT 时,微软遭受了 9 亿美元的损失,并且 Windows 应用商店中的应用程序严重缺乏。 这是一个标记为发布版本的 alpha 版本,因此应用程序开发人员拭目以待。 将近 8 年后的今天,它仍然是一个 alpha 版本,而且已经很晚了,我仍在等待、观察和等待。

如果微软能够做出认真的决定/承诺,优先生产真正的 UWP 测试版,然后快速推出真正的候选发布版本,这对微软和开发人员来说都是非常有益的。 这将是强烈推荐的,也是一个非常明智的行动方案。 对每个人都会很棒。

由于多种原因,UWP 仍然是 alpha/不完整,例如:25 年前,使用 Windows 95 中的“MoveFile”函数来移动文件或文件夹很容易(虽然该函数被命名为“MoveFile”,但它同时支持这两个文件)和文件夹)。 UWP 可以移动文件夹吗? 还没有。 显然,移动文件夹的能力是最基本的基本功能之一,但是 UWP 仍然缺少这个基本功能和其他功能,因此将 UWP 描述为功能完整是不合理的,因此 UWP 尚未达到测试状态,尽管7-8年前发布。 微软需要优先考虑真正的 UWP 测试版。

据我所知,用于跟踪 UWP 问题(UI 问题除外)的公共 GitHub 存储库尚不存在(或者如果 UWP 存储库确实存在,我找不到它)。 这再次符合 alpha 版本的定义,因为在 alpha 阶段通常不需要公共问题跟踪存储库。 如果它是真正的 Beta 版或发行版,那么公共问题跟踪存储库应该已经打开,并且 UWP 将包含 Windows 95 和 Windows 7 等的所有功能。

这种情况如何影响DataGrid ? 考虑到功能完备的 UWP Beta 版的推出实在是太迟了,考虑到这种情况的严重性以及微软因此遭受的数十亿美元的损失,浪费更多时间是不合理和合理的通过将 WinUI DataGrid 转换为非托管代码和较旧的编程语言。 微软一再表示 C# 和“托管代码”的一大优势是提高了生产力,我可以说微软关于“托管代码”的说法在我使用 C++ 和 C# 的经验中绝对是正确的。 如果 UWP 主要是使用从 1.0 版开始的托管代码编写的,那么几年前它就已经达到了真正的 beta 状态。 所以我希望情况不会因为从托管代码到非托管代码执行更多这些不必要的降级而变得更糟。

相比之下,WPF 大部分是在 2006 年到 2010 年的 4 年间成功完成的。WPF 主要是托管代码,与 UWP 不同。 UWP 是非托管代码,经过 8 年的发展,Windows 95 仍然在一些领域击败了 UWP,所以当微软声称托管代码可以提高生产力时,微软显然是正确的。 这个问题需要尽快解决。 WinUI 应该比 WPF 更容易/更快地创建,因为两个项目都有相同的所有者(Microsoft),因此 WinUI 可以自由地从 WPF 复制代码。 因此,WinUI 应该大约需要 WPF 一半的开发时间。 其实WinUI应该从来没有启动过,而是微软应该在新版本的WPF中开发WinUI的功能——WinUI应该是WPF 5.0。 所以,情况是一团糟,对微软来说,优先处理这个烂摊子的剩余清理工作,并停止做那些使数十亿美元的错误比现在更糟的事情(当你看时仍然如此)将是非常有益的。在今天的智能手机市场份额情况下)。

这意味着,为了防止更多的损失,微软将通过记住微软过去已经说过/知道的事情而受益:

  • 根据微软自己的说法,托管代码提高了生产力。 当您将 UWP 的 8 年与 WPF 的 4 年进行比较时,结论一定是 Microsoft 在托管代码的好处方面是正确的。
  • 脚本语言是用来编写脚本的,而编程语言是用来编程的。 JavaScript 和 PowerShell 非常适合它们的预期目的(脚本),但它们显然不适合应用程序编程。
  • 要取得成功,Microsoft 必须从 alpha 到 beta 再到发布,这只有在它是真正的发布版本时才能成功,而不是标记为“发布”的不完整 alpha。 因此微软商店大部分时间都是空的。
  • 软件工程师和其他员工在工作以换取合理的报酬和合理的工作时间以及健康的工作环境时工作得最好。 显然,微软数十亿美元的损失永远无法通过使用无偿的狂热分子/狂热者和他们所谓的“白天工作”和“夜间工作”以及不可持续/不健康的工作条件来扭转。
  • Android 的巨大市场份额胜利并不是因为没有报酬的狂热分子。 如果没有报酬的狂热分子是获胜的原因,那么 Linux 就不会失败。 解释要简单得多:Android 平板电脑和智能手机的价格远低于 Windows 平板电脑和智能手机。 显然,最终用户并不关心“开源”宗教/意识形态(用户甚至不知道那是什么),他们只是喜欢 Android 设备的廉价价格。
  • Win16 已经非常过时了。 这是 20 到 30 年前的技术,从早期的“狂野西部”编程时代开始。 因此,停止编写基于 Win16 的新代码。 称它为“Win32”并没有真正改变它本质上仍然是 Win16 的事实。 Win32 与 Win16 相同,只是指针的大小从 16 位扩展到 32 位。 Microsoft 中有太多团队继续编写基于 Win16/32 的新代码。 这是非常低效的,也是资源的极大浪费。

@anawishnoff

我们有兴趣将其升级为本机 WinUI 控件

另见维基百科的文章“沉没成本”

沉没成本效应(或协和效应)是行为往往遵循沉没成本谬误的事实; 人们表现出“一旦在金钱、努力或时间上进行了投资,就更倾向于继续努力”。 这种行为可谓“一掷千金”,不屈不挠,可谓“斩钉截铁”。

和类似的“计划延续偏差”

计划延续偏差、到达那里或压力是一种不明智的倾向,即坚持一个失败的计划。 这对于船长或飞机飞行员来说是一个危险的危险,他们可能会坚持计划的航线,即使这会导致致命的灾难,他们应该中止。 ..... 由于计划谬误和相关因素,包括过度乐观、不愿承认失败、集体思维和厌恶沉没成本的损失,项目经常遭受成本超支和延误。

WinRT/UWP 导致微软第一年或第二年亏损 9 亿美元,应用商店空置太久。 WinRT/UWP 是一场灾难性的失败,本应在第二年中止,但由于“计划延续偏差”和对沉没成本损失的厌恶而继续进行。 这些东西是在管理课程中教授的。 计划的延续是否最终消除或扭转了 WinRT/UWP 的灾难性失败? 不,如果您从智能手机市场份额的角度来看,它今天仍然是灾难性的失败。 维基百科中的那些描述准确地描述了 UWP 的情况。

现在今天我们都必须同意,在当前时间点,即 WinRT/UWP 发布后的 7-8 年,现在取消 UWP 为时已晚,但这意味着我们再次成为“计划延续偏见的受害者” “以及对沉没成本损失的厌恶。

那么怎样才能合理地挽救局面呢? 我们不能通过取消 UWP 来挽救这种情况,即使它在几年前肯定应该被取消。 我们能做的是:接受 WinRT 造成的巨大损害,但不要造成任何进一步的损害,并对项目的程序/政策进行更改。 这意味着,停止重复/继续 WinRT 的相同灾难性错误。 例如,停止将如此大量的托管代码降级为非生产性的旧非托管“本机”代码。 达到真正的 Beta 状态的延迟已经非常大了——为什么还要让延迟变得更糟?

如果 DataGrid 降级为非托管的“本机”代码,“计划延续偏差”/沉没成本错误将继续存在。 当出现 WinRT/UWP 等灾难性错误时,如果一次又一次地重复同样的错误,情况就会变得更糟。 为了限制损害,有必要停止重复同样的错误。 现在是从 WinRT 的灾难性失败中吸取教训并开始使用绷带来阻止持续失血的时候了。

将 DataGrid 转换为非托管代码就像去图书馆从知识/经验最丰富的最佳作者那里借用所有最好的项目管理书籍,然后将所有这些优秀的管理书籍扔进篝火,看着它们燃烧。

@verelpode我很好奇你在这里用 DataGrid 写的两篇非常大的帖子是什么意思。 我个人并没有真正理解上述反馈具体是指改进 OOB DataGrid 控件的内容。 我唯一得到的是您担心将其转换为本机代码是在浪费时间,但这并没有解决那些从 C++ 使用 WinUI 的人。 如果您对加载托管运行时的开销没有意见,您仍然可以自由使用当前的托管实现。 其他一切似乎都与 WinRT 和 UWP 应用程序模型有关,这两个模型都不适用于 WinUI,因为它与 v3 完全脱离了。

@dotMorten——我在这些消息中写了更多细节的原因是因为如果我没有充分解释问题,那么人们就不会理解它。 但遗憾的是,现在我看到额外的细节失败了,无论如何仍然无法理解。 这是非常令人沮丧的。 这就是为什么很多人根本懒得写任何反馈的原因,因为他们认为试图向人们解释这类问题是没有意义的,即使信息被成功理解,那么拍摄是人性的传达坏消息的人,最好什么都不说,或者只是“礼貌地”微笑着思考相反的事情。

因为它与 v3 完全脱离了。

此 v3 解除绑定并不能防止重复相同的错误。 “计划延续性偏差”依然存在。

进入微软主页:
https://www.microsoft.com/en-us/
现在向下滚动主页,直到您看到 Windows Phone。 哦! 看那个! 我们已经到了主页的末尾,微软主页上的任何地方都没有提到 Windows Phone! 这是什么意思? 意思是,醒醒。 正如我所说,这意味着 UWP 是一场灾难性的失败。 这意味着,停止重复导致 UWP 失败的相同错误很重要。 这意味着,为了抢救和从灾难中恢复,改变计划。
如果 WinUI 和 DataGrid 继续重复与 UWP 失败相同的错误,那将是一个管理错误。

“2016 年 5 月,微软砍掉了其移动业务,...... 2017 年,微软高管乔·贝尔菲奥雷透露,微软已经停止开发新的 Windows 手机和 Windows 10 移动版的新功能,理由是市场份额的损失和缺乏应用程序开发。”
-- https://en.wikipedia.org/wiki/Microsoft_Mobile

Ana 列出了 5 点来提供有关 wrt DataGrid 的反馈。 你是在评论这些观点中的哪一点? 我想那是我从你写的东西中没有得到的一点。 UWP 并不能满足所有人的需求,但 WinUI3 并没有规定使用 UWP 应用程序模型,而且您似乎主要反对 UWP? 所以你在那里应该没问题。

您提到 DataGrid 不应该继续犯同样的错误。 那么哪些错误是专门针对现有 DataGrid 的,您建议如何纠正这些错误? (除了由于某种原因你不希望它在 C++ 中实现)

@dotMorten

Ana 列出了 5 点来提供有关 wrt DataGrid 的反馈。 你是在评论这些观点中的哪一点?

我在信息开头引用安娜的那部分。 我正在评论我在信息开头引用的安娜信息的一部分。

WinUI3 不规定使用 UWP 应用程序模型

这与我的消息无关。 WinUI 3 未绑定并通过nuget 包可用与WinUI 3 是否继续导致UWP 和Windows Phone 失败以及微软数十亿美元损失的相同管理错误的问题无关。

你如何建议他们应该被纠正?

我之前的信息末尾的 6 个要点。 第二个要点(脚本)一般与 WinUI 和 UWP 相关,但与 DataGrid 无关。 如果您专门询问 DataGrid,则第一个要点是最重要的。
我还写道:停止将如此大量的托管代码降级为非生产性的旧非托管“本机”代码。 达到真正的 Beta 状态的延迟已经非常大了——为什么还要让延迟变得更糟?

@anawishnoff写道:

我们有兴趣将其升级为本机 WinUI 控件

“将其升级为本机 WinUI 控件”实际上构成了某些相同错误的延续/重复,这些错误导致维基百科中提到的“市场份额损失和应用程序开发不足”:

“2016 年 5 月,微软砍掉了其移动业务,...... 2017 年,微软高管乔·贝尔菲奥雷透露,微软已经停止开发新的 Windows 手机和 Windows 10 移动版的新功能,理由是市场份额的损失和缺乏应用程序开发。”
-- https://en.wikipedia.org/wiki/Microsoft_Mobile

为什么DataGrid 还要沿着摧毁微软移动业务的同一条道路继续前进?

@verelpode

WinUI 3 延续了导致 UWP 和 Windows Phone 失败以及微软数十亿美元损失的相同管理错误。

我不为微软工作,但我很好奇你为什么说 WinUI 正在犯管理错误。
从我看到的事实来看,WinUI 是开源的,每个人都可以参与对话和决策,这实际上有助于定义 WinUI 是什么,并且应该防止错误发生。
你提到 DataGrid 正在沿着与移动相同的路径继续前进,但我在球场上没有看到它提到移动。 也许您可以直接对此问题所讨论的内容进行反馈。
如果您觉得 WinUI 存在管理不善的步骤,那么也许您可以创建一个单独的问题来解决您的问题,但我真的不认为您的评论与 DataGrid 控件有任何关系。

@verelpode请在此处保持您的反馈主题。 如果您对 WinUI 或 UWP 有任何疑问,请开始一个新的讨论主题或直接与​​我联系(给我发电子邮件或在 Twitter 上 DM)。 或者您可以考虑讨论现有主题,例如 #717 或 #1531。

您分享了对用 C++ 重写 DataGrid 的担忧,但实际上最初的提案并未提及任何相关内容。 @anawishnoff正在尝试收集有关 DataGrid 功能集的反馈。 在实现方面,如果将它保留在 C# 中最有意义,我们会这样做(如果我们将它作为 WinRT 组件进行,它仍然可以从 C++ 调用)。

@jevansaks——我的反馈是

@verelpode没有人在这里“射杀传递坏消息的信使”。 @jevansaks邀请您打开一个新问题,在此存储库中分享您对 UWP/WinUI/WinRT 的广泛关注。 这个问题实际上仅与 DataGrid 相关,虽然您的担忧之一确实与 DataGrid 相关,但总体而言,绝大多数与 UWP/WinUI/WinRT 相关。 我敢肯定,如果您再次查看此讨论,您会发现 WinUI 团队只是要求您将此问题仅集中在 DataGrid 提案上,并针对您对平台。

您提到的问题可以成为涉及 WinUI 团队和社区的有趣讨论的基础,但这个特定问题不适合这样的讨论。

@anawishnoff
我很确定 Microsoft Pivot Viewer Control 不是 html。 请回头看看。 使用类似的东西可视化大量数据的能力是我们有时想做的事情。 我认为它在 Silverlight 中可用。 https://www.microsoft.com/silverlight/pivotviewer/default#它使用 Deep Zoom 来实现它的功能。 将深度缩放功能添加到 WinUI 3.0 会很棒! 不是真正的数据网格,而是数据显示控件。 有很多 WPF 早期的“被遗弃”的想法,比如 Deep Zoom,从未将其转化为生产 WPF 控件,随着时间的推移,这些想法在 WinUI 3.0 中恢复生机将是美妙的。 哎呀,去把 WPF 博士从地下室弄出来,让他再发帖!!! 我们需要他回来。 我们需要发起一场运动。 带回 WPF 博士 !!!!!! 你去哪儿了? WinUI 博士!!!

@PaulMontgomerySP听起来您应该打开一个新问题来讨论 Pivot 控件。 请随意在此处参考 Windows 社区工具包中有关它的先前讨论: https :

我用键盘移动到的每一行都会触发选择更改事件。
最好有一个仅用于鼠标单击或单元格点击的事件,而不仅仅是选择更改事件。

选择更改事件同时触发点击和键盘。 拥有一个仅用于点击的事件将大有裨益。

@Going-Gone 我很好奇它的用例是什么? 为什么需要知道区别? 你也不能使用点击事件吗?

我刚刚使用 UWP 工具包的 DataGrid 遇到的一个限制是DataGridTemplateColumn有一个 CellTemplate,但它没有CellTemplateSelector (同样缺少CellEditingTemplate )。 它将使用选择器方法简化使每个单元格中的 UI 适应数据的过程,而不是必须使用它下面的额外级别的 UI 控件来处理它。

还请使不仅可以像我在此处详细解释的那样按连续顺序选择行:
https://github.com/duke7553/files-uwp/issues/276#issue -520060100

客户经常要求网格应该支持的事情没有特定的顺序

1.能够保存、加载和构建过滤器。 例如过滤到 linq 表达式,过滤到 SQL 查询,过滤到表达式树,反之亦然。 示例 - https://querybuilder.js.org/demo.html

  1. 高速实时数据功能,性能很重要。 交易应用程序的低于 1 毫秒的刷新率与 > 100 万行的刷新率具有不同的性能考虑因素。
  2. 能够指定排序顺序,例如 i。 排序高/低,ii。 排序低/高和iii。 没有排序或我。 排序低/高,ii。 排序高/低和iii。 没有排序
  3. 类似Excel的过滤
  4. 能够将 css 格式应用于单元格、条件格式
  5. 能够轻松保存/加载网格设置,例如过滤器、列宽、排序等
  6. 滚动有效,例如数据更新后不会重置,平滑。
  7. 数据收集事件应该具有在加载范围而不是单个对象后触发事件的选项。 例如,我相信 ObservableCollection 需要子类来防止为每个添加的单个对象触发 INotifyPropertyChange。
  8. 更好的事件,用于数据加载/加载、数据加载开始、数据加载、数据加载,尤其是在使用异步加载时。
  9. 网格通常链接到其他控件,例如数据过滤器、范围选择、交叉过滤器(例如 https://github.com/dc-js/dc.js)、图表、数据透视表等
  10. 处理字母数字数据的智能排序,例如排序顺序 ABC11、ABC12、ABC111 而不是 ABC11、ABC111、ABC12
  11. 无限级别的分层网格,例如https://docs.telerik.com/devtools/wpf/controls/radgridview/hierarchical-gridview/hierachy-overview

有用的资源: - 设计更好的数据表
https://news.ycombinator.com/item?id=21460966
https://uxdesign.cc/design-better-data-tables-4ecc99d23356

我将无法直接从 Header 绑定到 Columwidth。 在 WPF 中,在这种情况下我必须使用 BindingProxy 对象。

方便地动态调整活动行的大小,以便于编辑。
在编辑模式下完全控制上下文菜单。

希望它像 Telerik 一样支持 CellDecorationStyleSelector。

无障碍!
提及它以便对其进行记录,但此控件需要完全可访问。
当前的工具包版本在这方面有一些限制: https : https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/3079
此外,虽然 Telerik RadDataGrid 有一些很棒的功能,但它似乎不支持可访问性

随着 Microsoft 大力推动 D&I,我很惊讶所有控件都完全可访问的需求并未在任何地方指定为要求。

也许这已经是可能的,我只是不知道如何完成它......但是如何:自定义行或单元格样式?

定位特定行、更改背景和文本颜色的能力会很棒。

与 WCT UWP DataGrid 相比:
1) 性能
2)更多的内置列类型(我认为它们比模板列具有更好的性能)
3) 能够为每个单元格挂钩鼠标事件,即点击、右键点击和悬停,(或指针向下或其他)
4) 每个单元格的键盘事件
5)如果(3)不可行,我们可以模拟是否有命中测试功能
6) 性能

如果 WinUI DataGrid 放弃最终用户能够在 DataGrid 内内联/直接编辑单元格值的功能,有多少人会提出异议?

有人记得VB6吗? VB6 DataGrid 支持开箱即用的 Edit、Delete 和 AddNew。 添加可用作自动添加到列表末尾的空白行。 完成该行并出现另一个空白行。

DataGrid 应该具有支持数据输入的选项,即使大多数开发人员更喜欢将此功能默认为关闭。

在将 VB6 应用程序移植到 UWP 时,我们必须编写自己的数据网格来支持添加/编辑/删除。

似乎在这里做出贡献的大多数是 WPF/Xaml 人员,这对于不是 xaml 人员的人来说价值两美分。

我在我的软件中经常使用 DataGrid 控件。 编辑是地方很重要! 我的一些愿望/痛点是:

  1. 能够在编辑模式下自定义上下文菜单。
  2. 自动调整列大小时,性能更好,控制更多。 我希望用户能够在必要时控制尺寸,但大多数情况下不需要。 我不希望列大小不断变化,但我希望它们以某种方式基于数据,而不必测量一百万行的数据。
  3. 编辑时,我希望能够单击不同的控件/按钮,该控件/按钮对(或与)正在编辑的数据执行某些操作,而无需结束编辑。 (如果实施#1,这将不太必要 - 尽管仍然有用。)
  4. 当前使用 DataError 事件处理异常的方式很粗糙。 (抱歉,我无法具体说明这一点,但我知道它过去曾多次让我感到痛苦。)
  5. 内置自动滚动功能会很好: http :
  6. 能够显示“水印”,指示数据何时“脏”(有关DataGridView的一些其他有用增强功能,请参阅
  7. 当所需的“关键”单元格留空时,能够放弃一行(没有验证错误)。
  8. 为用户添加的行不显示图像(而不是红色 X)的内置功能。 请参阅: https :
  9. 允许复选框列在更改时立即提交: https :

alpha预计什么时候发布? 会开放投稿吗? 试图抛弃过时的数据网格并非常期待这一点,尤其是虚拟化功能。

很抱歉在此线程中输入了很晚的内容,但对我来说它是“新的”;)
_在进一步了解控件的行为方式后进行了编辑_

在与 DataGrid 合作为云驱动器制作类似资源管理器的界面时,我发现确定被点击的行和单元格可能比它“应该”更复杂(恕我直言)

在我的应用程序设计中,行代表文件或文件夹 (DriveItems)。 详细视图显示有关该项目的更多详细信息。

我想创建一个点击文件夹项目的能力,让界面跳转并创建这些项目的列表,允许在整个驱动器中导航。

image

例如,如果我点击项目的“父”列条目/drive/root:/Documents/Vital%20Documents此处,界面将重置为该文件夹并列出那里的文件。

尽管可以为单元格获得单击事件,但该事件似乎没有处理程序的上下文来确定被点击的单元格(行,是,但不是列),而且我不确定当前控件将允许我同时拥有单元格点击行为和自动打开细节行为(仍在调查我可能称之为“黑客”的内容,但我们必须提醒自己,当设计师开始覆盖控件的正常功能时,尤其是不是记录在案的行为,它们冒着设计被控件行为改变破坏的风险。

所有这一切都说,DataGrid 似乎支持我的方案,通过将当前将 DriveItem 返回为 CurrentItem 的事件,还应该包括一个CurrentColumn ,它将是在其中单击的整个DataGridColumn对象,通过可以提取列名。 我现在确实意识到我们有可以从事件中调查的 CurrentColumn 对象,所以,虽然我更喜欢它作为事件参数,但这应该有效。

此外,对详细信息行为的更严格控制可能是,详细信息只会在单击特定列时自动展开,而不是在单击行中的任意位置时展开。

也许DataGridColumn对象的基类可以有一个ExpandDetails属性,默认情况下可以将每列设置为 true,这意味着单击特定列会导致行展开。 其他属性为假的则不会。

例如,在我的设计中,第一列是项目类型,如文件或文件夹、图像或照片、音频等。我可能会设想将该列设置为唯一导致自动展开行为的列,然后单击“路径”列可能会导致我上面描述的“获取该路径的列表”行为。

至于排序,实现足够的控制以允许设计人员获得多级排序在逻辑上似乎很重要。 我还没有做过调查来确定当前控件如何通过挂钩/覆盖事件和回调来支持这一点,但它看起来并不简单。

最后,我知道您很清楚这一点,但是(即使我要求更多功能),让我们请避免尝试添加一堆复杂的行为,用户可以在 DataGrid 之上实现自己。 其中我不会在 DataGrid 中实现的是与外部存储过滤器或排序等有关的任何内容。我也将避免将此控件制作为 excel 克隆。

-谢谢,干得好!
-e

粘性组:当浏览具有大组的数据集时,应该有关于正在查看哪个组(或组,即面包屑)的上下文。 这似乎是所有基于分层列表的视图的基本可用性功能:分组列表视图、数据网格和树视图。

我将在新的 WinUI ItemsRepeater 控件之上构建新的 DataGrid 控件。 该控件将其 ItemsSource 作为对象公开:
Object ItemsSource { get; set; };

@RBrid大约 1 年后回到这个

  • ISupportIncrementalLoading
  • 项目范围信息
  • 选择信息

- 现在在那里获得 MVP 怎么样,这样我们就可以使用 c++ 中的 Datagrid。

此页面是否有帮助?
0 / 5 - 0 等级