Microsoft-ui-xaml: Discussion: Modern WinUI DataGrid - Input Needed

Created on 28 Oct 2019  ·  81Comments  ·  Source: microsoft/microsoft-ui-xaml

Discussion: Modern WinUI DataGrid

Hey community members! We've seen that DataGrid has been a valuable piece of the Windows Community Toolkit for many of you and we are interested in graduating it to a native WinUI control (!!). I need your help to figure out what would be needed to make a full-scale DataGrid the best it can be.

I want to hear your input on all things DataGrid. To get started, feel encouraged to answer as few or as many questions as you have time for:

  1. What are some wish-list items that you want for DataGrid?
  2. Where can DataGrid improve in terms of UI, UX, and overall design?
  3. What do you like/dislike about DataGrid?
  4. What are some scenarios in which you use DataGrid?
  5. Are there any scenarios that you wish it could fit better into?

Thanks in advance everyone! See below links for some refreshers and context.

Related Links


Read up on the DataGrid documentation
Download and interact with DataGrid via the DataGrid Nuget package download
Refresh your knowledge by checking out the existing open source DataGrid implementation in the WCT.

discussion

Most helpful comment

My wishlist : to me a good datagrid includes all the following features by default. I'm borrowing some screenshots from the html world.

Easy filter the whole page with preferred row count.

1

Select / Deselect Visible Columns , Column Sorting , Copy , Print

2

Export data to specific format.

3

Column Reordering by dragging column.

4

Column Filtering

5

Fixed Header - where header stays on top even when scrolling

Row details with XAML template for details.

6

Row Grouping

7

Drag & Drop Row Order

8

The features above in my opinion should be standard in all datagrids.

If you want to make datagrid stand out to the html world then I would also include the following. I find myself many times looking at a datagrid and then settling on a listview as the datagrid lacks these features.

Sideswipe the row to include features like edit , delete , flag etc.

sideswipe

The above features handle mainly the "presentation of data" , what is still lacking from WinUI is what I believe should be a native WinUI feature (control ) like the Microsoft Pivot Control. to compliment the datagrid.

MS already has the source code for this and it was an absolute awesome control back in the days.

pivot1

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

Now you cover the presentation and visualization of data that should be the minimum to set WinUI apart from all the basic features out there.

Most importantly it really displays the power of "native apps" that should include awesome animations and visually appealing controls that is powerful and looks really cool.

I can take this one step further and say after the above features (visualizations) we can include 2D/3D animations that creates a concept of depth in the data and will take us to a different stratosphere , but I guess that is for another day ;))

uwp2

All 81 comments

More viewmodes. Take a look at File Explorer and it's Icon views. The DataGrid should be able to show icons/items in a grid with grouping, as well as the headed rows and columns.

I know this may not be possible, or out of scope - but it is an aspect of WinUI vs Win32 that isn't as easy as 1:1 - and a modern version of File Explorer, or the Common File Dialogs - may have need of such a control. This could be that control, not an internal custom control.

My wishlist : to me a good datagrid includes all the following features by default. I'm borrowing some screenshots from the html world.

Easy filter the whole page with preferred row count.

1

Select / Deselect Visible Columns , Column Sorting , Copy , Print

2

Export data to specific format.

3

Column Reordering by dragging column.

4

Column Filtering

5

Fixed Header - where header stays on top even when scrolling

Row details with XAML template for details.

6

Row Grouping

7

Drag & Drop Row Order

8

The features above in my opinion should be standard in all datagrids.

If you want to make datagrid stand out to the html world then I would also include the following. I find myself many times looking at a datagrid and then settling on a listview as the datagrid lacks these features.

Sideswipe the row to include features like edit , delete , flag etc.

sideswipe

The above features handle mainly the "presentation of data" , what is still lacking from WinUI is what I believe should be a native WinUI feature (control ) like the Microsoft Pivot Control. to compliment the datagrid.

MS already has the source code for this and it was an absolute awesome control back in the days.

pivot1

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

Now you cover the presentation and visualization of data that should be the minimum to set WinUI apart from all the basic features out there.

Most importantly it really displays the power of "native apps" that should include awesome animations and visually appealing controls that is powerful and looks really cool.

I can take this one step further and say after the above features (visualizations) we can include 2D/3D animations that creates a concept of depth in the data and will take us to a different stratosphere , but I guess that is for another day ;))

uwp2

A good starting point is looking at your partner Telerik with their RadDataGrid (UWP Open Source). With one of my clients, I used it and it actually works well. It is hyper fast and versatile. The only thing that is difficult is their code, there is no way to modify anything from their engine without a good comprehension of the architecture.

I would expect the new DataGrid to be as performant as Telerik.

I'm very glad to see the WinUI team is considering a DataGrid control.

The most substantial improvements I'd like to see from a new control to replace the Toolkit DataGrid:

  • The ability to retrieve a DataGridRow by index
  • Events specific to the DataGridRows themselves. For instance, DoubleTapped and RightTapped.
  • Smooth scrolling
  • Input validation for cell renames
  • A DataGridColumn designed specifically for row icons
  • Easy customization of colors, etc.

The option to have an edit button which puts draggable icons next to each row to move the order would be a useful feature. It would also be great to see some shadows behind the row being lifted up and moved (since one of the main Fluent attributes is depth). Small up and down arrows might be good next to the dragging icon to move the rows more easily with mouse input. If a row is moved using the arrows, a subtle sliding animation would be a nice touch. With touch input, the option to hold on a row and just move it without even needing to press the edit button might work well too. I'm not sure if this is already supported, but I could see selection check boxes like in File Explorer making obvious which DataGrids support row selection and just improve the overall UX. The iOS reminders app contains some of these ideas (examples pictured below). The iOS Stocks app also has a similar sort of deal with movable rows. Most of these ideas would also work great for columns.

123456

IMG_1820 (1)

@NoahFeller That type of action makes more sense for a List View. With a Grid view you are not rearranging the order, there should be sort options but the user is not dragging things around.

*Edit
After thinking about it a little more, I do see how such an option can be useful. However, I definitely don't think this should be the default behavior.

@NoahFeller That type of action makes more sense for a List View. With a Grid view you are not rearranging the order, there should be sort options but the user is not dragging things around.

*Edit
After thinking about it a little more, I do see how such an option can be useful. However, I definitely don't think this should be the default behavior.

Yeah you're probably right @yaichenbaum. I was envisioning those suggestions as the ability to do a custom sort and I thought dragging might be useful for that. So I agree, definitely not default but it might be pretty useful as an option. Thanks for the feedback!

The simplicity of the WPF datatable to datagrid function. I've actually been fighting for the past week or so trying to get a UWP datagrid to work how I had it in WPF where I could just bind a Datagrid to a Dataview, then fill the Dataview from SQL with a datatable.defaultview. The grid then just displayed the data table. It was amazingly simple to do, and UWP so far has made this ridiculously complicated.

make it cross platform

I would like to request a single cell selection mode, excel style.
The ultimate goal being a mode with the exact behaviour as a WinForms DataGridView.

Having an assortment of virtualization options that can support different use cases (From plain scrolling virtualization options like recycling to other concepts like data paging)
Often (In similar desktop controls that support this) some of these options begin to fail when used with custom templates for columns with unique data. The more they can support in those cases, the better.

If at all possible, the Paging Control #268 proposal, should be synced, and any hooks required be added to the DataGrid control.

This is good news! I've been waiting for something official on the DataGrid front for a while ever since it appeared in the community toolkit. This is really the last control missing from WinUI 3.0 that the community toolkit doesn't have a good alternative for.

First, please, don't reinvent the wheel. As a base start with the WPF implementation of the DataGrid (I know you can't use the code but please use 100% of the API) -- NOT the Silverlight one. The WPF DataGrid was much more feature-complete and has fewer bugs in my testing.

In using the community toolkit DataGrid I also requested the following API additions that came up for various use cases Discussion here:

  • RowPressed : As discussed above. Indicates a row has been pressed so further processing or context menu's can occur.
  • RowDoublePressed : Same as RowPressed, just the double click version.
  • ColumnHeaderPressed : Occurs whenever a column header is pressed. Must take priority over any sort direction internal updates. This will allow for custom filtering menus or right click options to turn on/off columns.
  • ColumnHeaderDoublePressed : Same as ColumnHeaderPressed, just the double click version.
  • ColumnHeaderWidthChanged : Occurs whenever the user resizes a column header width. This will allow for saving this information in a clean way. This is commonly needed when restoring UI state.

I also continue to have lots of problems with the community tookit DataGrid resetting the scroll position to the top after ItemsSource is changed. This needs to get fixed so the offset is preserved like in WPF; however, we also need to be able to control this which is why I would suggest the following API as well:

  • FirstRowInView() : Returns the first row visible in the DataGrid used to restore state.
  • VerticalOffset : Get/Set again to restore state of the scrollbar
  • HorizontalOffset : Get/Set to restore state of the scrollbar

@RBrid Also helped with some analysis here:

Suggested new events, and some improvements to preexisting events:

| Event | Comments |
| :--- | :--- |
| ContextRequestedForColumnHeader | To support showing a context menu (or other flyout) when a column header is right-clicked. The same as Windows.UI.Xaml.UIElement.ContextRequested but for column headers instead of the entire DataGrid. |
| ContextCanceledForColumnHeader | The same as Windows.UI.Xaml.UIElement.ContextCanceled but for column headers instead of the entire DataGrid. |
| ContextRequestedForRow | To support showing a context menu (or other flyout) when a row is right-clicked. The same as Windows.UI.Xaml.UIElement.ContextRequested but for rows instead of the entire DataGrid. |
| ContextCanceledForRow | The same as Windows.UI.Xaml.UIElement.ContextCanceled but for rows instead of the entire DataGrid. |
| RowTapped | Note also the case of tapping a row that is already selected. |
| RowDoubleTapped | The same as Windows.UI.Xaml.UIElement.DoubleTapped but for rows instead of the entire DataGrid. |
| RowRightTapped | The same as Windows.UI.Xaml.UIElement.RightTapped but for rows instead of the entire DataGrid. See also ContextRequestedForRow. |
| PointerPressedInRow | The same as Windows.UI.Xaml.UIElement.PointerPressed but for rows instead of the entire DataGrid. |
| PointerReleasedInRow | The same as Windows.UI.Xaml.UIElement.PointerReleased but for rows instead of the entire DataGrid. |
| PointerMovedInRow | The same as Windows.UI.Xaml.UIElement.PointerMoved but for rows instead of the entire DataGrid. Possibly PointerMovedInRow would only be triggered while the pointer is captured. |
| ColumnHeaderTapped | Note also the case of tapping a column header that is already selected. |
| ColumnHeaderDoubleTapped | The same as Windows.UI.Xaml.UIElement.DoubleTapped but for column headers instead of the entire DataGrid. |
| ColumnHeaderRightTapped | The same as Windows.UI.Xaml.UIElement.RightTapped but for column headers instead of the entire DataGrid. See also ContextRequestedForColumnHeader. |
| ColumnHeaderWidthChanged | Alternatively could be named ColumnHeaderResized. In the event args, include a boolean property that specifies whether it was changed by the user versus changed programmatically. Obviously the event args should also specify which column header was resized/changed. |
| SortOrderChanged | Should be triggered when the list of selected column headers changes. Also triggered when any of the selected columns is switched between ascending versus descending order. In the event args, include a boolean property that specifies whether the sort order was changed by the user versus changed programmatically. See also preexisting event Sorting. I think a new event SortOrderChanged would be triggered after the Sorting event is triggered, if the sorting isn't cancelled. |
| Sorting | Already exists but consider adding a settable boolean property in event args that allows the sorting request to be cancelled. For example, the sorting may be invalid or unable to be performed and needs to be cancelled. Also add a boolean property to specify whether sorting was requested by the user versus programmatically. |
| ColumnSortDirectionChanged | This event could be created but it could be unnecessary if the aforementioned SortOrderChanged event is created, if SortOrderChanged is also triggered when the sort-direction changes. |
| ColumnDisplayIndexChanged | Already exists but please consider adding a boolean property (in event args) that specifies whether it was changed by the user versus changed programmatically. Also, please document why it's necessary to have both of the ColumnDisplayIndexChanged and ColumnReordered events. Alternatively, eliminate one of these events. |
| ColumnReordered | Already exists but please consider adding a boolean property that specifies whether it was changed by the user versus changed programmatically. |
| SelectionChanged | Already exists but please consider adding a boolean property (in event args) that specifies whether it was changed by the user versus changed programmatically. |
| CopyingRowClipboardContent | Already exists but please consider adding a boolean property to the event args that specifies whether the operation is cut instead of copy. Alternatively make a separate event for cut. |
| CuttingRowClipboardContent | Doesn't exist. Consider making an event that is triggered when user attempts to cut rows (via control-X hotkey, context menu, or otherwise). Alternatively make the aforementioned boolean property that would allow CopyingRowClipboardContent to be triggered for both of copy and cut operatoins |
| PastingRowClipboardContent | Doesn't exist. Consider making an event that is triggered when user attempts to paste (via control-V hotkey, context menu, or otherwise). |

I think the most important feature for me would be the ability to easily handle a million rows or more, without having to load a millions rows into memory. The ISupportIncrementalLoading interface isn't good enough for this, because the scroll bar only reflects how many rows you have loaded so far (not total count), and to get to row 1 million, you'd have to keep scrolling to the end over and over and load more and more data, and hope I won't run out of memory. But if I know I have 1 million data records, let me tell the datagrid that, and if I scroll fast or jump to the end, I can be asked to just provide the last few rows.
Think scrolling through a list of rows in a database that I'll be dynamically pulling in.

I think the most important feature for me would be the ability to easily handle a million rows or more, without having to load a millions rows into memory. The ISupportIncrementalLoading interface isn't good enough for this, because the scroll bar only reflects how many rows you have loaded so far (not total count), and to get to row 1 million, you'd have to keep scrolling to the end over and over and load more and more data, and hope I won't run out of memory. But if I know I have 1 million data records, let me tell the datagrid that, and if I scroll fast or jump to the end, I can be asked to just provide the last few rows.
Think scrolling through a list of rows in a database that I'll be dynamically pulling in.

This.

'Modern' means lightweight and quick, and enterprise apps are commonly about sorting through tons of internal data to find and explore the appropriate records. Paging, sorting, async incremental loading, endless scrolling - all of these are staples of desktop apps which leverage data grids.

MS should produce a sample app which highlights these features in the new grid and collect feedback from enterprise developers over time to make these experiences better. Have it run off of a large dataset like World Wide Importers to demonstrate its effectiveness.

@dotMorten

I think the most important feature for me would be the ability to easily handle a million rows or more, without having to load a millions rows into memory.

I wish for that as well. In order to assist with supporting a million rows (and I mean assist, not necessarily the complete solution), I suggest that DataGrid should make its current data-binding technique optional. I believe currently data-binding is mandatory (unless my knowledge is no longer up-to-date with the latest version of DataGrid). DataGrid shouldn't require use of Windows.UI.Xaml.Data.Binding as the only supported way of retrieving the values for each cell/column in each visible row.

I suggest that DataGrid allow apps to give DataGrid a delegate or interface instance that DataGrid will invoke whenever DataGrid needs to retrieve the value of a cell/column in a row (alternatively, this delegate or interface could retrieve the entire row -- all column values for a specified row).

Ideally (if possible), DataGrid would allow this delegate or interface to operate asynchronously. For example, the delegate or interface might return a Task or IAsyncOperation<TResult> instead of immediately returning the requested value.

Alternatively, asynchronous support is also possible without Task and IAsyncOperation<TResult>, if DataGrid operates similar to the following procedure:

  1. DataGrid decides that it needs to retrieve the value of cell/column 5 in row ID 50001. Alternatively DataGrid decides to retrieve all column values for row ID 50001.
  2. DataGrid invokes a delegate or interface instance or event handler that notifies the app that DataGrid has requested the loading of the data values of the specified column/row or entire row.
  3. The app retrieves the requested row data asynchronously. For example, it could asynchronously perform an SQL database query.
  4. The app finishes retrieving the requested row data. The app invokes a method in DataGrid that gives the row data to DataGrid.
  5. DataGrid displays the row data, or does whatever else it needed to do with the data.

First off, wow!! Thanks so much to everyone who's contributing their ideas. I have a few specific responses below, but overall I wanted to say that I am saving a ton of these comments and really enjoying hearing how we can build an awesome modern DataGrid. Keep it coming!

@Pinox thanks so much for that detailed response and the screenshots. Your wishlist is awesome (especially those cool animations!) - I agree that those features found in html are a good inspiration point and are simple but would greatly improve quality of life. Will definitely be saving this comment for future reference!

@verelpode, @robloo, @duke7553 YES to DataGrid-specific events! Thank you all for the detail you put into these. As we design for touch-first and for a variety of inputs, events like these should definitely be implemented!

@dotMorten, @jkewley, @verelpode Performance is definitely one of the main motivations for this project and one of the main improvements we want to implement, through a new data virtualization story and the use of modern controls such as ItemsRepeater. Will keep you all updated once we have more specifics - but thanks again for these details youve suggested.

@Laz3rPanth3r, @robloo, @keeganatorr We hear you loud and clear about liking the DataGrids that belong to WPF and other UI frameworks - we are definitely taking this into account in this refresh!

Thanks for the great work on DataGrid and the request for feedback! Here are a few more suggested enhancements.

Need more subclasses of DataGridColumn

The current subclasses/implementations of DataGridColumn are insufficient. I suggest making the following new subclasses of DataGridColumn:

| Proposed Subclass | Description |
| :--- | :--- |
| DataGridIconColumn | A common requirement is to display an icon in each row of a list, therefore I suggest making a DataGridColumn subclass named DataGridIconColumn that typecasts the retrieved cell value to Windows.UI.Xaml.Controls.IconSource and renders the IconSource instance (a different IconSource instance is rendered in each cell). |
| DataGridImageColumn | DataGridImageColumn should operate the same as the proposed DataGridIconColumn except that it should render Windows.UI.Xaml.Media.ImageSource instead of Windows.UI.Xaml.Controls.IconSource. |
| DataGridDateTimeColumn | Displays date and/or time, depending on settings. Typecasts the cell value to System.DateTimeOffset or System.DateTime (both supported) and converts it to text to be displayed in the cell. The conversion to text should be controlled by formatting settings/properties in the DataGridDateTimeColumn class. Obviously sorting by date/time must also be supported. |
| DataGridTimeSpanColumn | Typecasts the cell value to System.TimeSpan and converts it to text to be displayed in the cell. The conversion to text should be controlled by formatting settings/properties in the DataGridTimeSpanColumn class. Obviously sorting must also be supported, and it must sort the TimeSpan instances not the displayed text. |
| DataGridDataSizeColumn | Typecasts the cell value to System.Int64, UInt64, Int32, or UInt32 (all supported) and converts it to a size-in-bytes (as text) to be displayed. For example, 1572864 would be displayed as "1.5 MB" because 1572864/1024/1024 = 1.5. The conversion to text should be controlled by settings/properties in the DataGridDataSizeColumn class. Sorting must be performed using the original integer value not the displayed text. |
| DataGridCustomColumn | This should operate similar to the preexisting DataGridTemplateColumn except without the Windows.UI.Xaml.DataTemplate. It should invoke a delegate/callback or event to generate and/or update the displayed GUI element subtree. |
| DataGridTextColumn | Already exists but please consider adding properties or events that allow apps to override the object-to-text conversion and the comparison function for sorting. I explain this in more detail later in my message. |

DataGridCustomColumn would be like this:

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
}

When the event DataGridCustomColumn.DisplayingCell is triggered, the event handler should generate or update its own UIElement subtree to display the DataGridDisplayingCellEventArgs.CellValue, and set the property DataGridDisplayingCellEventArgs.CellUIElement to that UIElement subtree, and then DataGrid will display it.

The next time DataGrid triggers this event, DataGrid should set the property DataGridDisplayingCellEventArgs.CellUIElement to the UIElement instance that was previously generated by the event handler, in order to allow the event handler to reuse/recycle and update the same UIElement subtree (potentially with a different value in DataGridDisplayingCellEventArgs.CellValue). The event handler is allowed to either recycle the same UIElement subtree OR set the property DataGridDisplayingCellEventArgs.CellUIElement to a newly created UIElement subtree.

Also consider the possibility of making the new DisplayingCell event directly in the base class DataGridColumn, instead of making the subclass DataGridCustomColumn. Thus the event DataGridColumn.DisplayingCell could allow customization or overriding of the generated UIElement for every subclass of DataGridColumn.

In the preexisting DataGridTextColumn, currently the cell value/object is converted to text for display by invoking System.Object.ToString. Please consider making a delegate/callback or event that allows apps to override this value-to-text conversion. Please also consider a property that allows apps to specify a System.Collections.IComparer instance to override the sorting behavior.

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

public delegate string DataGridCellValueToToStringConverter(object sourceObject);

Alternatively, instead of making the Comparer property in DataGridTextColumn, consider the possibility of making the Comparer property directly in the base class DataGridColumn, in order to allow apps to control the sorting behavior for all subclasses of DataGridColumn.

Likewise the CellValueToToStringConverter property could also be made in the base class DataGridColumn because it would be useful to have the ability to convert any cell value to text regardless of which subclass of DataGridColumn is used. For example, when copying a row to the clipboard, each cell value could be converted to text. (Both text and non-text formats may be simultaneously placed in the clipboard -- apps commonly do this in order to increase compatibility with other apps.)

Re sorting when a DataGridIconColumn or DataGridImageColumn is selected: Obviously DataGrid cannot sort icons or images, therefore it could use any one of these solutions:

  • Simply disallow end-users to select (sort by) a column header of type DataGridIconColumn or DataGridImageColumn.
  • Make an AlternativeText property in the IconSource class. When DataGridIconColumn sorts the rows, or when it converts the cell to text for the clipboard/copy, it would use the AlternativeText property.
  • Make a settable Comparer property (of type System.Collections.IComparer) in either DataGridColumn or DataGridIconColumn.

Access to selected rows/items

Please consider improving the functionality for getting and setting the selected rows/items, because the current functionality is insufficient. Currently these properties exist:

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

I found that sometimes I needed access to the DataGridRow instances of the selected rows, thus I hope that the following properties can be added to DataGrid:

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

Alternatively, if the above is too difficult to implement, the following read-only variation is less powerful but still helpful:

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

If DataGridRow instances may be recycled, then the documentation for the above properties should warn that the returned info is only temporarily valid, thus it should be read/used immediately and not retained for a longer length of time.

Also, the preexisting SelectedIndex property gives access to one selected index, but what about getting access to all of the selected items? Therefore I suggest making the following SelectedIndexes property:

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

Personally I find the name "SelectedIndex" confusing because DataGrid is often used in conjunction with a database and the term "index" has a completely different meaning in a database, therefore I suggest renaming the properties as follows, but I expect that my naming suggestion will be rejected:

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

I also wish for the ability to scroll the specified DataGridRow and/or DataGridColumn into view. Currently this method exists:

public void ScrollIntoView(object item, DataGridColumn column);

I suggest replacing the preexisting ScrollIntoView method with these 2 methods:

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

Get and set sort-order in one hit

When apps are opened and closed, they need the ability to save and restore the end-user's configuration of the DataGrid, including the sort order and other settings. Sort order meaning the list of columns that were selected by the user. Note this is a list, not a single column. More than one column may be selected simultaneously, meaning the primary column for sorting, and the secondary column for sorting, and the tertiary column for sorting, etc.

Therefore the following property could be made in DataGrid, but actually this is only the first idea and it isn't ideal:

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

The above is non-ideal because it doesn't support the saving and restoring of the DataGridColumn.SortDirection of each column in one hit. I realize that apps could do it in multiple steps:

  1. Set the proposed SortOrder property to the list of selected columns.
  2. Set the SortDirection property of each of the selected columns (repeat this step for each column).

That's still problematic because it's multiple hits, meaning it causes multiple time-consuming resorts of the DataGrid. End-users could notice and suffer a significant delay in a DataGrid that contains a large number of rows, when the DataGrid is resorted multiple times unnecessarily. To eliminate this problem, I suggest the following solution that allows apps to restore the complete sort-order in one hit and cause no more than a single resort.

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

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

Note I deliberately wrote IReadOnlyList<DataGridColumnAndDirection> not IList<DataGridColumnAndDirection> above because apps shouldn't be able to modify the list returned by the SortOrder property. Instead of modifying the list, apps should set the SortOrder property to a list that DataGrid will copy and use to completely replace the entire sort order list. Thus it would operate in one hit and avoid multiple expensive resorts.

When DataGrid.SortOrder is set to a new list, DataGrid would also set the corresponding DataGridColumn.SortDirection property in each column in the new SortOrder list, but without causing multiple resorts. Thus DataGrid.SortOrder[i].SortDirection is equivalent to DataGridColumn.SortDirection.

Get and set displayed column order in one hit

When apps are opened and closed, they need the ability to save and restore the end-user's ordering of the columns, preferably in one hit. I know that the preexisting property DataGridColumn.DisplayIndex is settable, therefore theoretically apps could restore the end-user's configuration by iterating through all columns in DataGrid.Columns and set the DisplayIndex of each, but this might cause bugs. For example, DisplayIndex might fail or behave in an unexpected manner when an app needs to temporarily set the DisplayIndex of one column to the same DisplayIndex of another column. Also, if it isn't performed in one hit, then it could trigger multiple expensive redraws and/or recalculations.

Therefore I suggest making a ColumnDisplayOrder property in DataGrid:

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

The same as I mentioned previously for SortOrder, ColumnDisplayOrder is deliberately IReadOnlyList<DataGridColumn> not IList<DataGridColumn> because it should operate in one hit.
When DataGrid.ColumnDisplayOrder is set to a new list, DataGrid would update the DataGridColumn.DisplayIndex of each column to match.

Allow end-users to hide/show columns

Consistent with the preexisting properties DataGridColumn.CanUserReorder etc, I suggest making a CanUserChangeVisibility property in DataGridColumn. When DataGridColumn.CanUserChangeVisibility is true, the end-user would be able to cause changes to the property DataGridColumn.Visibility.

Support GUI elements generated dynamically at runtime

Allow the row-details GUI to be generated without requiring the use of DataGrid.RowDetailsTemplate (Windows.UI.Xaml.DataTemplate). In order to achieve this, some thought needs to be put into the API, but here's my first idea for how to do it: Maybe do it via the preexisting event DataGrid.LoadingRow by changing the property DataGridRowDetailsEventArgs.DetailsElement to be settable so that the event handler can generate (or update) the UIElement by itself and give it to DataGrid by setting the DetailsElement property.

The reason why mandatory use of Windows.UI.Xaml.DataTemplate is a problem: Although templates are a good feature, the template concept expects a precreated unchanging XAML snippet/document that was written by the developer in advance. Thus templates are a problem when the app needs to dynamically generate the GUI at runtime. Thus I wish for the aforementioned alternatives to DataTemplate.

Drag-and-drop of rows, inwards and outwards

I suggest making the ability to optionally enable outgoing drag-and-drop of rows. DataGrid would implement the drag but not the drop. When the drop occurs, DataGrid would trigger an event and the app responds to the event in order to perform the desired action when the row is dropped outside of the DataGrid.

Also the ability to optionally enable incoming drag-and-drop of rows or items/objects. DataGrid would accept incoming drag-and-drop but does not implement the drop. DataGrid would trigger an event when the row/item/object is dropped, and the app responds to the event in order to to perform the desired action when the row is dropped inside the DataGrid.

Individual cell backgrounds

We have a feature request from a customer who wants individual cells to be hilited (by changing the cell background color/brush) at certain times (such as when our app detects changes or important values or dangerous values exceeding safety limits etc).

Thus I could propose a DataGridCell.Background property (of type Brush), but I think this way of doing it is probably defective because DataGrid recycles DataGridCell instances, doesn't it? So I guess that hiliting individual cells by setting a DataGridCell.Background property would be an unreliable solution.

A better way might be via the event DataGridColumn.DisplayingCell that I proposed in my previous message. The event handler could set a CellBackgroundBrush property in DataGridDisplayingCellEventArgs.

Dumb-down DataGrid's retrieval of data (cell values)

I know "dumb" sounds very bad, but in reality I would love it if DataGrid was made dumb in the area of data-retrieval (retrieval of the cell values to be displayed by DataGrid).

Currently DataGrid attempts to perform data retrieval in a convenient automatic manner via its property DataGrid.ItemsSource plus data-binding techniques (the property DataGridBoundColumn.Binding), and interfaces such as System.ComponentModel.INotifyPropertyChanged.

Yes data-binding is a convenient feature, but actually I'd much prefer to have DataGrid do _less_ in that department! Several Microsoft components actually cause large difficulties for me via their behavior of trying to be smart but actually ending up being too smart. Overall I'd actually experience fewer difficulties and less work if these components would cease trying to be so smart/automatic/convenient. When designing an automatic behavior, I find it worthwhile to keep in mind that automatic sounds great but has the potential to backfire.

_"Just simply let me do it by myself."_
Sometimes the best solution is to just simply allow apps to perform the task by themselves, instead of trying-and-failing to do it "automatically" inside a component such as DataGrid. I wish that DataGrid would allow me to completely perform the data retrieval by myself, instead of trying to automatically retrieve the data via the properties DataGridBoundColumn.Binding and DataGrid.ItemsSource.

Ideally I'd like to eliminate the requirement to use the property DataGrid.ItemsSource to supply the items. @dotMorten mentioned a million rows. Currently DataGrid makes it mandatory for apps to set DataGrid.ItemsSource, but it is impractical to create a list object that contains a million items. Thus I wish that DataGrid would stop being smart in the data-retrieval department and instead let me completely perform the data retrieval by myself, without using DataGridBoundColumn.Binding and DataGrid.ItemsSource.

@anawishnoff wrote:

Performance is definitely one of the main motivations for this project and one of the main improvements we want to implement, through a new data virtualization story and the use of modern controls such as ItemsRepeater.

I see you said the new data virtualization story will improve performance, and that's good news, but will it also eliminate the requirement to use the property DataGridBoundColumn.Binding in order to supply the cell values that DataGrid displays?

If the entire data retrieval job is outsourced to the app that uses DataGrid, then the app has complete flexibility to perform the data retrieval in any manner that it needs. This would enable many different data-retrieval scenarios, including the million rows that @dotMorten mentioned. Dumb it down, please :smile:

A few unnecessary features in WPF DataGrid?

The WPF version of DataGrid has a few features that seem unnecessary or impractical, and these features could be skipped in WinUI DataGrid, but I expect that some people probably have a different opinion about these features.

How many people would raise an objection if WinUI DataGrid abandoned the feature where end-users are able to edit cell values inline/directly inside the DataGrid? In our case, in every place where we use DataGrid, we always set DataGrid.IsReadOnly to true to disable the inline/direct editing feature. We allow users to edit the selected row in a separate pane or panel, or in RowDetails (DataGrid.RowDetailsTemplate), but not directly inside the DataGrid itself.

It seems like WinUI DataGrid has already moved in the direction of dropping support for inline/direct editing because WPF DataGrid had CanUserAddRows and CanUserDeleteRows but these properties don't exist anymore in WinUI DataGrid. Why not go all the way to dropping the inline/direct editing feature entirely? How many people have objections to this idea?

Individual cell selection: WPF DataGrid has a SelectionUnit property that you can set to Cell, FullRow, or CellOrRowHeader. In our case, we always set it to FullRow and never found a need to set it to Cell. However I see one person here has already requested single cell selection mode. My question is whether cell selection mode is a common or rare request.

On the other hand, individual cell selection might be useful when the user copies rows/cells to the clipboard. It would allow users to copy an individual cell (or several contiguous cells) to the clipboard instead of copying the entire row. However I'm unsure whether this feature is truly valuable or not.

| Dubious Feature in WPF | Comments |
| :--- | :--- |
| DataGrid.IsReadOnly | Maybe no real need to ever set IsReadOnly to false? |
| DataGrid.CanUserAddRows | Doesn't exist in WinUI DataGrid. Already abandoned, or maybe not yet implemented (I don't know the plan). |
| DataGrid.CanUserDeleteRows | Doesn't exist in WinUI DataGrid. Already abandoned, or maybe not yet implemented (I don't know the plan). |
| DataGrid.SelectionUnit | Doesn't exist in WinUI DataGrid. |

Wow, incredible discussion here. ❤️

I also agree to the WPF DataGrid API. The WPF DataGrid is really the DataGrid I want for WinUI 3.0.

But even the WPF DataGrid lacks some features. In the past, most of my customers used a more powerful 3rd party DataGrid to get these features:

  • Filters in the Column Headers
  • A complete filter row at the top of the DataGrid
  • Powerful display of hierarchical data. Some 3rd party DataGrids really work like a powerful TreeView with nested DataGrids. While the WPF DataGrid allows to build something like that, it doesn't support it out of the box
  • Support for different data types. Like for example a DateTime column. In WPF's DataGrid you have to use the DataGridTemplateColumn

But anyway, what ever you do, I think building a DataGrid is a powerful statement and commitment to WinUI 3.0. For LOB applications you can't take a UI framework serious that doesn't contain a built-in DataGrid. And it's great to see this investment made for WinUI!

@thomasclaudiushuber

For LOB applications you can't take a UI framework serious that doesn't contain a built-in DataGrid. And it's great to see this investment made for WinUI!

Agreed! In our case, DataGrid is a critically essential component that we use in multiple places and cannot live without.

Powerful display of hierarchical data. Some 3rd party DataGrids really work like a powerful TreeView with nested DataGrids.

I'm torn on that topic because -- like you -- I would find a hierarchical DataGrid useful in some situations, but my concern is that if DataGrid does implement hierarchical functionality, then it could become excessively complex and difficult, and the release of DataGrid would most likely be delayed substantially. New features would be difficult to add because of the complexity of making new features compatible with both hierarchical and non-hierarchical functionality.

To eliminate the aforementioned complexity/delays problem, I suggest this solution: Make a separate class named HierarchicalDataGrid that internally uses/wraps an instance of DataGrid. Alternatively HierarchicalDataGrid could publicly inherit DataGrid but I suspect this inheritance is impractical, therefore I prefer to suggest that HierarchicalDataGrid inherit Control and internally have a private field of type DataGrid. Thus the hierarchical functionality would be implemented in the HierarchicalDataGrid layer that directs an internal non-hierarchical DataGrid instance.

The key advantage of the above solution is that would deliver the desired hierarchical features _without_ bogging down DataGrid, without making DataGrid so complex that it becomes unmanageable and slow to develop.

Support for different data types. Like for example a DateTime column.

I agree. Check out the DataGridDateTimeColumn and DataGridTimeSpanColumn that I proposed in a previous message.

@Pinox

Easy filter the whole page

@thomasclaudiushuber

Filters in the Column Headers; A complete filter row at the top of the DataGrid;

Filters would be great for helping end-users quickly find a row or rows, instead of the current situation of being forced to manually look at a large number of rows to find what they're looking for.

But what about the problem of matching the user's filter text with non-text columns? Meaning columns other than DataGridTextColumn, such as filtering with DataGridTemplateColumn etc? I suggest solving this with something approximately like the following solution that gives DataGridColumn (and subclasses) the ability to convert a cell value to keywords for use with searching/filtering/matching.

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

Here is an example of how to use the ConvertCellValueToKeywords method:

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

Alternatively, the cell value could be converted to a single string instead of a collection of keywords, but the reason why I suggested a keywords collection is that keywords make it possible to use searching algorithms that run at high speed even when the quantity of rows is very large.

Easy copy past from excel
Now there no way to use ctrl+v to copy Excel cells content to datagrid. Now it copy all cells content to one cell in data grid.

Please provide a proper multiple selected items support, by making SelectedItems as a dependency property to allow using data binding when managing selected rows.

@verelpode I can see individual cell selection being useful for any spreadsheet type application, no? I think it matters more in edit scenarios vs. view scenarios. When viewing data in a datagrid without edit, I agree I wouldn't see a use for individual cell selection and always have full row selection.

@anawishnoff I think @Laz3rPanth3r would agree and the couple of issues here and here from the toolkit that being able to ingest data easily and simply into the DataGrid is an important feature. You should be able to boot-strap the grid by binding to a collection of objects or expando objects in a list. If it can intelligently select columns for numbers and strings and basic data types, that'd be great. The developer can always do more work after to customize individual columns beyond that.

I can see individual cell selection being useful for any spreadsheet type application, no?

In a spreadsheet, the column headers are named with ascending letters of the alphabet, A, B, C, D, … and the type of every column is the same, as if every column uses DataGridTextColumn and no other column type is needed, and column names aren't really needed either because they're generated automatically from the alphabet.
Another difference between DataGrid and a spreadsheet is that a spreadsheet doesn't sort the rows when you click any of the column headers.

My point is, only a superficial similarity (mostly a visual similarity) exists between DataGrid and a spreadsheet. DataGrid doesn't really operate like a spreadsheet. The cell data retrieval technique of DataGrid is also poorly suited to a spreadsheet.

I love DataGrid but it would function poorly if I tried to use it to implement a spreadsheet. I don't think DataGrid is the right choice for anyone who wants to implement a spreadsheet.

The existing design of DataGrid aligns far better with an SQL database than a spreadsheet, and SQL database developers would yell loudly if someone tried to claim that a database is "just a spreadsheet".

@verelpode Your contributions are so detailed and thought-out, thank you so much for all of that! I want to talk about the idea of binding a data source/the ItemsSource property of DataGrid, as you mentioned and @michael-hawker did as well.

Currently DataGrid makes it mandatory for apps to set DataGrid.ItemsSource, but it is impractical to create a list object that contains a million items. Thus I wish that DataGrid would stop being smart in the data-retrieval department and instead let me completely perform the data retrieval by myself, without using DataGridBoundColumn.Binding and DataGrid.ItemsSource.

This is interesting, and I'd like to look more into it as we are really interested in performance. What sort of data situation/scenario are you looking for, specifically? Would you want to connect the DataGrid straight to an SQL query result, or a database, or something along those lines?

@khoshroomahdi By copy and paste, do you mean you'd want to copy excel cells into a DataGrid in a running app, and populate in that way? That's an interesting use case, I'd like to hear more.

@alexyak, could you expand a bit further? The SelectedItems property currently allows you to get all selected items in a DataGrid (through extended selection mode though, not precisely multiple selection mode). I see from a few other comments here that selection within a DataGrid definitely needs work, but I want to understand your request better.

@anawishnoff yes exactly.
I have some data in excell cells and want to copy them in running app.

For non-data-bound scenarios, we should look at how the WinForms DataGridView control, which I wrote many years ago, supported a virtual mode: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview.virtualmode

Currently DataGrid makes it mandatory for apps to set DataGrid.ItemsSource, but it is impractical to create a list object that contains a million items. Thus I wish that DataGrid would stop being smart in the data-retrieval department and instead let me completely perform the data retrieval by myself, without using DataGridBoundColumn.Binding and DataGrid.ItemsSource.

I agree that would be nice as well. I'm thinking something like ListBox where you can either add Items manually or set the ItemsSource. That said, in the past I just generate a new DataTable representing a partial view of the full database to implement paging (which is a good use case for this). A view of that DataTable can then be set to ItemsSource. So while I definitely think this is nice to have it doesn't seem mandatory for high performance.

Concerning all the comments turning the control into more-or-less a subset of Excel(r), I think out of the box the DataGrid should support cell selection and per-cell editing. However, things like copy/paste between external applications should be handled by the developer.

@alexyak Concerning your request to making SelectedItems a real, bindable DependencyProperty this would be great to restore state as well (most of my feature requests so far are to restore view state). I think this is a framework-wide issue though as it's not supported in any WinUI/UWP controls I am aware of. This should probably be a general feature request. See discussion here

@anawishnoff wrote:

Your contributions are so detailed and thought-out, thank you so much for all of that!

Thanks, I'm glad to hear that my contributions are useful in making DataGrid even better :)

What sort of data situation/scenario are you looking for, specifically? Would you want to connect the DataGrid straight to an SQL query result, or a database, or something along those lines?

That's still too smart. This smart behavior prevents different apps from performing the data retrieval in different manners. Different apps have vastly different circumstances, thus the "best" data retrieval system is different for different apps -- no single "best" exists. For example, some apps never display more than a couple hundred rows, whereas some other apps may work with a million rows like @dotMorten mentioned, therefore one shoe size does not fit all.

I suggest really dumbing it down to this level:

  1. DataGrid decides that it needs to display (or otherwise use) the value that exists in column 5 of row 9001 in the external data storage system.
  2. DataGrid notifies the app that it needs the value for column 5 of row 9001.
  3. The app retrieves the value for column 5 of row 9001. This may involve an async SQL query, or an async C# Task, or any other data system. Ideally DataGrid should allow this step to be async.
  4. The app notifies DataGrid that it finished retrieving the value for column 5 of row 9001. The app gives this value to DataGrid.
  5. DataGrid uses the value in whatever manner it needed to, such as displaying the value as mentioned in step 1.

@RBrid wrote:

For non-data-bound scenarios, we should look at how the WinForms DataGridView control, which I wrote many years ago, supported a virtual mode:

Yes yes yes! I've never used WinForms DataGridView, but I just read the documentation now and I believe you've hit the nail on the head. The webpage you linked to says:
_"Virtual mode is designed for use with very large stores of data."_

I see that the WinForms DataGridViewCellValueEventArgs contains these properties:

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

That's excellent, except that ideally it should be updated to support the modern C# async and await keywords, or the UWP equivalent (IAsyncOperation<TResult>), or rather any kind of time delay between DataGrid requesting the cell value and the app delivering the cell value to DataGrid. Thus to update it to support async, do this:

  1. Keep the event CellValueNeeded.
  2. Remove the property DataGridViewCellValueEventArgs.Value.
  3. Create a method in DataGrid named something like SupplyCellValue that the app will invoke, instead of being required to immediately/synchronously set the property DataGridViewCellValueEventArgs.Value.

The SupplyCellValue method might be defined like this:

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

Thus at runtime the procedure is:

  1. DataGrid decides that it needs to display (or otherwise use) the value that exists in column 5 of row 9001 in the external data storage system.
  2. DataGrid triggers the event CellValueNeeded and sets DataGridViewCellValueEventArgs.RowIndex to 9001 and DataGridViewCellValueEventArgs.ColumnIndex to 5.
  3. The event handler (the app) starts running an async task that will retrieve the value for column 5 of row 9001.
  4. When the async task finishes running, meaning when the app has retrieved the value, the app invokes the method DataGrid.SupplyCellValue.

This dumbed-down technique is more powerful and flexible than the smart automated technique of DataGridBoundColumn.Binding and DataGrid.ItemsSource.

@alexyak, could you expand a bit further? The SelectedItems property currently allows you to get all selected items in a DataGrid (through extended selection mode though, not precisely multiple selection mode). I see from a few other comments here that selection within a DataGrid definitely needs work, but I want to understand your request better.

We need a proper two way databinding for viewmodels to manage multiple selections

@verelpode, we had modeled the WinForms DataGridView model after the even older Win32 ComCtl32 controls. In particular, I'm thinking about how the list-view control used the LVN_GETDISPINFO message in virtual mode (see https://docs.microsoft.com/en-us/windows/win32/controls/list-view-controls-overview#handling-virtual-list-view-control-notification-codes and https://docs.microsoft.com/en-us/windows/win32/controls/lvn-getdispinfo). Old stuff from the '90.

Anyways, I believe the way the asynchronous data retrieval aspect should be handled is through 'deferred events'.
WinUI controls already use deferred events twice:

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

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

It's the pattern the new DataGrid's CellValueNeeded event would want to adopt. It allows the event handler to supply data asynchronously and tell the control when it's done doing so. See https://docs.microsoft.com/en-us/uwp/api/windows.foundation.deferral.

@RBrid
Good point about GetDeferral() being the new standard pattern. In this particular case of CellValueNeeded, it seems much more difficult to use Deferral than in other cases/events. Correct me if I'm wrong, but I think the problem with using GetDeferral() in this particular case is that GetDeferral() creates a new object every time it is invoked, and this would lead to an excessively huge amount of object creation and clean-up being repeated for every cell of every row of a potentially large number of rows. I haven't seen the source code of various GetDeferral() implementations therefore I could be mistaken about this.

In other words, unless Deferral supports recycling or otherwise has a way of making GetDeferral() much more efficient, then it's still too smart. My dumbed-down proposal with the SupplyCellValue method avoids incurring the overhead of creating, completing, and disposing a new Deferral instance for every cell of every applicable row.

  1. GetDeferral()
  2. Deferral.Complete
  3. Deferral.Dispose
  4. Repeat the above steps a large number of times.

The task of retrieving a cell value is not the only data management task that may be outsourced to the app. Sorting might also be outsourced. Therefore it might be worthwhile to consider thinking of an interface instead of a single event CellValueNeeded. An app would give DataGrid a data management module in the form of an object that implements a certain interface. DataGrid would invoke this interface in order to retrieve cell values, but also potentially other tasks such as sorting.

To support the million rows that @dotMorten mentioned, CellValueNeeded alone wouldn't solve the other problem that occurs when the user clicks a column header and the DataGrid tries to sort a million rows. Thus cell retrieval AND sorting could be outsourced to the app via the aforementioned module/interface.

If the app doesn't supply any data management module/object to DataGrid, then ideally DataGrid would use a default data management module. Thus all of the existing data-binding code in DataGrid would be moved out of DataGrid and into a separate new class -- the class that implements the default data management module by working with DataGridBoundColumn.Binding etc.

i.e. when sorting is also outsourced to the app or its data management module, then this opens the door to various solutions that support a million rows, such as writing a data management module that instructs the SQL server to perform the sorting, instead of trying-and-failing to do the sorting of a million rows inside DataGrid in less time than 10 or 20 hours after the user clicks the column header to begin the sorting.

@verelpode, yes that's a valid concern. I would expect the DataGrid to own a pool of recyclable Windows.Foundation.Deferral objects. We would need to confirm the feasibility and perf for sure.

Having taken a dependency on the Windows Community Toolkit DataGrid which has Row Details as a feature (albeit with a serious performance bug but with a workaround), we would really like this new datagrid to have that as a feature as well - with the same option to have multiple row details concurrently. Using it for a server to client streaming data scenario.

Re a million rows versus a paging GUI, @robloo wrote:

I agree that [supporting a million rows] would be nice as well. .... That said, in the past I just generate a new DataTable representing a partial view of the full database to implement paging (which is a good use case for this). A view of that DataTable can then be set to ItemsSource. So while I definitely think this is nice to have it doesn't seem mandatory for high performance.

Paging is a useful technique and worthwhile mentioning, but it has substantial disadvantages: It makes DataGrid's sorting feature practically useless. Likewise for a filtering feature in the next version of DataGrid. Paging makes sorting and filtering useless or at least much less useful.

For example, imagine that 2 or 3 columns are date columns, and the user wants to view the rows that have the most recent (or the oldest) date in the second date column. Thus the user clicks the second date column header to sort the DataGrid by that column, and also clicks to change sort-direction from descending to ascending or vice-versa. This works great if no paging is in-use, or if the total quantity of rows is small enough to not exceed a single page, but it breaks if multiple pages exist.

The user needs to find the most recent (or oldest) date across all rows but a paged DataGrid GUI only shows the most recent (or oldest) date in the current page, not across all rows, thus paging makes sorting (and filtering) practically useless.

This raises the question of which rows land in which page. The answer is that each page typically contains a practically-random subset of the rows, when the pages/rows are obtained via an SQL SELECT query that doesn't use ORDER BY. (I mean random from the user's point-of-view, not truly random.)

Pseudo-random is unhelpful for end-users. To eliminate this problematic randomness, we could think about using SQL ORDER BY (along with the ASC or DESC keyword to control sort-direction), and then yes the pages are no longer random, but it's still broken because this usage of ORDER BY always sorts by the same column and same sort-direction, meaning the sort order is frequently different than the sort order chosen by the end-user clicking on a column header in DataGrid.

To fix it, you would need to use a different SQL query each time the user clicks on a different column header. The SQL ORDER BY ... ASC/DESC would need to be kept the same as whatever sort order is chosen by the end-user of DataGrid. DataGrid does not support this currently.

A suggested solution is in my previous message: I've suggested that DataGrid should allow sorting to be outsourced to the app (or to a "data management module"). This idea would make it possible for the app (or "data management module") to change the SQL ORDER BY ... ASC/DESC whenever the end-user changes the sort-order of DataGrid by clicking on column headers etc.

It might also be worthwhile to give the preexisting event DataGrid.Sorting a settable property in the event args that allows apps (the event handler) to cancel the sorting and take over. Ideally the event args would also specify whether the sort order change was requested programmatically versus requested by the end-user clicking on column headers etc. In this case, it might also help to rename the event DataGrid.Sorting to something less ambiguous because currently the intention and purpose of the Sorting event is unclear. See also the proposed event SortOrderChanged in my other message.

Having taken a dependency on the Windows Community Toolkit DataGrid which has Row
Details as a feature (albeit with a serious performance bug but with a workaround), we would
really like this new datagrid to have that as a feature as well - with the same option to have
multiple row details concurrently. Using it for a server to client streaming data scenario.

Link to the Row Details performance issue: https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/2842
Repro: https://github.com/observito/DataGridRowDetailsPerfTest

A good starting point is looking at your partner Telerik with their RadDataGrid (UWP Open Source). With one of my clients, I used it and it actually works well. It is hyper fast and versatile. The only thing that is difficult is their code, there is no way to modify anything from their engine without a good comprehension of the architecture.

I would expect the new DataGrid to be as performant as Telerik.

The syncfusion grid features are great but they aren't mvvm friendly. So you could do better.

Hey again all! Let's keep this conversation going. What are your thoughts on the DataGrid documentation that currently exists?

Here's a link to the main documentation page that links to all of the other relevant pages.

If we create a new DataGrid, we want to make sure the documentation that accompanies it will be top-notch, easy to understand, and addresses all of the issues and scenarios that are important to our developers.

_What are some topics you wish we had? What are some topics that could be clarified?_

Hey again all! Let's keep this conversation going. What are your thoughts on the DataGrid documentation that currently exists?

Here's a link to the main documentation page that links to all of the other relevant pages.

If we create a new DataGrid, we want to make sure the documentation that accompanies it will be top-notch, easy to understand, and addresses all of the issues and scenarios that are important to our developers.

_What are some topics you wish we had? What are some topics that could be clarified?_

Images showing typical DataGrid setups, along with the xaml and code to make them, would be useful.

Images showing typical DataGrid setups, along with the xaml and code to make them, would be useful.

@mdtauk Are there any specific DataGrid setups that you find to be "typical", or use cases in which you consistently find DataGrid being the best choice to use?

Images showing typical DataGrid setups, along with the xaml and code to make them, would be useful.

@mdtauk Are there any specific DataGrid setups that you find to be "typical", or use cases in which you consistently find DataGrid being the best choice to use?

I think for the WinUI 3.0 timeframe, showing common WPF, Win32 data grid/icon view scenarios. As well as what Microsoft considers Fluent/Modern DataGrid UI designs.

That is if the idea behind the control, is to encourage moving from old UIs to WinUI 3

@anawishnoff I think some of the questions we had from the toolkit in terms of things people were looking for documentation on where more of these scenarios as well:

  • Theming/Re-templating/Alignment
  • Data Binding (in general and in XAML)
  • Event/Selection Handling/Casing
  • Editing behaviors (especially edit on click)
  • Multi-paging (which should pair well with #60 and #268)

    • Loading animation coordination while data loads

  • Copy/Paste/Formatting
  • Different Column Data Types (and custom ones) (e.g. enums)
  • Context Menus
  • Accessibility

I noticed that the existing Toolkit DataGrid requires a IEnumerable for it's ItemsSource property. While this seems like a logical decision, it makes setting the object returned by Windows.Storage.BulkAccess.FileInformationFactory.GetVirtualizedItemsVector() as this property impossible. (Unless there is a way to cast the object returned) Furthermore, other controls like ListView and GridView support setting their ItemsSource property to a value of the object type. I'm not certain, but supporting this would likely allow for a more responsive user interface during storage operations.

@mdtauk Are there any specific DataGrid setups that you find to be "typical", or use cases in which you consistently find DataGrid being the best choice to use?

I think for the WinUI 3.0 timeframe, showing common WPF, Win32 data grid/icon view scenarios. As well as what Microsoft considers Fluent/Modern DataGrid UI designs.

That is if the idea behind the control, is to encourage moving from old UIs to WinUI 3

Win32 example (File Explorer)
image

WPF example
image

Fabric Web example
image

UWP example
image

@mdtauk Thanks for those screenshots! I definitely think it's important to highlight the key elements that have worked in previous versions of the control and document how they can be achieved with the new control.

@michael-hawker Awesome. I'm already seeing a few topics in there that have been brought up multiple times on this thread, so those are definitely a good place to start.

@duke7553 I'm not 100% sure about a solution to that, or if supporting an object type would be wise. Maybe @RBrid can chime in?

@anawishnoff & @duke7553, I would build the new DataGrid control on top of the new WinUI ItemsRepeater control. And that control exposes its ItemsSource as an Object:
Object ItemsSource { get; set; };

Hope it support CellDecorationStyleSelector as in Telerik.

@anawishnoff

we are interested in graduating it to a native WinUI control

hmmmm when you say "graduating", would that include downgrading it to C++? Currently WinUI's DataGrid is written in C#. I hope that "graduate" won't mean "downgrade". Importantly, WinUI needs to reach a point where the WinUI team can say that WinUI is better than WPF in every way that matters, but this goal is terribly overdue. This goal will become even more overdue if time/resources are wasted in unnecessary downgrades of code such as DataGrid from C# to C++.

Although there originally existed a reason for writing WinRT/UWP/WinUI in C++, unfortunately that reason didn't reach fruition, and Google/Android took most of the smartphone marketshare, therefore the original reason for using C++ isn't applicable anymore (easily said in hindsight, but not so easy to say earlier). If WinUI was written in C# from the beginning, then the better-than-WPF goal would have been achieved 3 years ago, but now it's 8 years and still not achieved, and nobody is able to accurately say when the goal will be reached. Hopefully the better-than-WPF goal and the WinUI DataGrid "graduation" goals won't be delayed by an unnecessary conversion to an older and less productive programming language.

I'm biased in favor of C++ because I started programming in C++ before C# even existed, and people prefer to stick with what they originally learned, and fondly remember _"the good old days"_. Despite my bias in favor of C++, I stopped writing C++, and I think DataGrid shouldn't be downgraded to C++ and delayed. Leave it as C# and focus on more important things such as making the various improvements suggested by people in this issue, and achieving the better-than-WPF goal before 1 decade is reached.

I love many aspects of WinUI, and I appreciate the many clever improvements in it, and I write app code for WinUI, but do you want to know the honest truth? The truth is, sadly I've not yet released any WinUI app to users, ever. The software released to the users is written with WPF, and the users don't care because the software works well and includes GUI modernizations. Although I've written a whole bunch of app code for WinUI, it's all preparation, planning, testing, waiting, not actually in-use by the users. Hopefully next year the first WinUI component will be released to the users, but I will appreciate this switch-over much more than they will. The users will hardly notice the switch-over, if all goes to plan.

From Microsoft's point of view, WinRT/UWP is release-quality software, published to users since the year 2012, but from my point of view, UWP is still a big experiment. For me, UWP (including WinUI) is all a big beta-test version that I've been playing around with for years.

During the first few years of UWP, every year I thought: _"errr… I'll wait until next year. There are still too many things in WPF that are missing in UWP. Surely next year will be better."_
Then the next year came and I repeated the same thought. Then the next year came and I repeated the same thought. Hopefully this year is the last year of saying that, or at least that's my intention.

WinUI can't afford more delays. Leave WinUI's DataGrid as C# code. Start writing more WinUI code in C# in order to increase productivity. It's now 8 years and Android has taken massive marketshare. That's a severe situation.

By the way, I was actually being nice/generous when I said that UWP is still a beta version, because technically UWP matches the definition of an alpha version, not beta. To be a true beta version, it needs to be feature-complete, but UWP has not yet reached feature-complete status, therefore UWP is still alpha. For example, Wikipedia's "Software release life cycle" article says:

"Beta phase generally begins when the software is feature complete but likely to contain a number of known or unknown bugs."
"Alpha software may not contain all of the features that are planned for the final version."

Wikipedia defines "feature complete" as follows:

"A feature complete version of a piece of software has all of its planned or primary features implemented but is not yet final due to bugs, performance or stability issues. This occurs at the end of alpha testing of development."

It would be unreasonable to describe UWP as feature-complete because if it's truly feature-complete, then UWP must have all the capabilities of Windows '95 plus more, but it doesn't -- UWP does not yet exceed Windows 95 in all areas. Windows 95 was released 25 years ago. When UWP/WinRT was released 7-8 years ago, Microsoft suffered a $900 million loss and a crippling lack of apps in Windows Store. It was an alpha version labelled as a release version, thus app developers waited and watched. Today, nearly 8 years later, it's still an alpha version and very overdue, and I'm still waiting and watching and waiting.

It would be very beneficial for Microsoft and developers if Microsoft would make a serious decision/commitment to prioritize the production of a true beta version of UWP, to be quickly followed by a true Release Candidate version. This would be highly recommended and a very sensible course of action. It'd be excellent for everyone.

UWP is still alpha/incomplete for multiple reasons, for example: 25 years ago, it was easy to use the "MoveFile" function in Windows 95 to move a file or folder (although the function was named "MoveFile", it supported both files and folders). Can UWP move folders? No. Not yet. Obviously the ability to move folders is one of the fundamental basic essential features, but UWP is still missing this essential feature and others, therefore it'd be unreasonable to describe UWP as feature-complete, therefore UWP has not yet reached beta status, despite being released 7-8 years ago. Microsoft needs to prioritize a true beta version of UWP.

A public GitHub repo for tracking UWP issues (other than UI issues) does not yet exist, as far as I know (or if a UWP repo does exist, I couldn't find it). Again this matches the definition of an alpha version because a public issue-tracking repo is often undesired during an alpha stage. If it was a true beta or release version, then a public issue-tracking repo would have already been opened, and UWP would include all the features of Windows 95, and Windows 7, and more.

How does this situation affect DataGrid? Considering that a feature-complete beta version of UWP is so terribly overdue, and considering the severity of this situation and the multi-billion dollar loss that Microsoft has suffered as a result, it wouldn't be justifiable and reasonable to waste even more time by converting WinUI DataGrid to unmanaged code and an older programming language. Microsoft said repeatedly that a big advantage of C# and "managed code" is increased productivity, and I can say that Microsoft's claims about "managed code" were definitely true in my experiences with both C++ and C#. UWP would have reached true beta status several years ago if it was primarily written using managed code starting with version 1.0. So I hope the situation won't be made even worse by performing even more of these unnecessary downgrades from managed code to unmanaged code.

For comparison, most of WPF was completed successfully in the 4 years from 2006 to 2010. WPF is primarily managed code, unlike UWP. UWP is unmanaged code and after 8 years of development, Windows 95 still beats UWP in a few areas, so Microsoft was clearly correct when Microsoft claimed that managed code increases productivity. This problem needs to be solved ASAP. WinUI should have been much easier/faster to create than WPF because both projects have the same owner (Microsoft) thus WinUI is freely allowed to copy code from WPF. Thus WinUI should have required roughly half the development time of WPF. Actually WinUI should have never been started, rather Microsoft should have developed WinUI's features in new versions of WPF -- WinUI should have been WPF 5.0. So, the situation was a big mess and it would be very beneficial for Microsoft to prioritize the remaining cleanup of this mess, and cease doing things that make the multi-billion dollar mistake even worse than it already was (and still is when you look at today's smartphone marketshare situation).

This means, in order to prevent even more losses, Microsoft would benefit by remembering what Microsoft already said/knew in the past:

  • Managed code increases productivity, according to Microsoft's own claims. When you look at UWP's 8 years in comparison to WPF's 4 years, the conclusion must be that Microsoft was correct re the benefits of managed code.
  • Scripting languages are for scripting, and programming languages are for programming. JavaScript and PowerShell are good for their intended purposes (scripting), but they're obviously unsuitable choices for the programming of apps.
  • To be successful, Microsoft must progress from alpha to beta to release, and this only succeeds if it's a true release version, not an incomplete alpha labelled as "release". Thus Microsoft Store was mostly empty for an excessively long time.
  • Software engineers and other employees work best when they work in exchange for reasonable remuneration and a reasonable number of working hours, and a healthy working environment. Obviously, Microsoft's multi-billion dollar loss will never be reversed by use of unpaid fanatics/zealots and their so-called "day jobs" and "night jobs" and their unsustainable/unhealthy work conditions.
  • Android's huge marketshare win wasn't thanks to unpaid fanatics. If unpaid fanatics were the reason for the win, then Linux wouldn't have failed. The explanation is far far simpler: The price of Android tablets and smartphones is MUCH lower than Windows tablets and smartphones. Obviously the end-users don't care about "open source" religions/ideology (users don't even know what that is), rather they just simply love the cheap prices of Android devices.
  • Win16 is extremely obsolete. It's tech from 20-30 years ago, from the early "Wild West" days of programming. Therefore, stop writing new code based on Win16. Calling it "Win32" doesn't really change the fact that it's still fundamentally Win16. Win32 is the same thing as Win16 except with the pointers expanded in size from 16 bits to 32 bits. Too many groups at Microsoft continue to write new code based on Win16/32. This is very inefficient and a big waste of resources.

@anawishnoff

we are interested in graduating it to a native WinUI control

See also Wikipedia's article "Sunk cost":

The sunk cost effect (or Concorde effect) is the fact that behaviour often follows the sunk cost fallacy; people demonstrate "a greater tendency to continue an endeavor once an investment in money, effort, or time has been made." This behavior may be described as "throwing good money after bad," and refusing to succumb to it may be described as "cutting one's losses."

And similarly "Plan continuation bias":

Plan continuation bias, get-there-itis or press-on-itis is an unwise tendency to persist with a plan that is failing. This is a dangerous hazard for ship's captains or aircraft pilots who may stick to a planned course even when it is leading to fatal disaster and they should abort instead. ..... Projects often suffer cost overruns and delays due to the planning fallacy and related factors including excessive optimism, an unwillingness to admit failure, groupthink and aversion to loss of sunk costs.

WinRT/UWP caused Microsoft to suffer a $900 million loss in the first or second year, and an empty app store for far too long. WinRT/UWP was a catastrophic failure, thus it should have been aborted in the second year, but it was continued because of the "Plan continuation bias" and the aversion to loss of sunk costs. This stuff is taught in management courses. Did the plan continuation eventually erase or reverse the catastrophic failure of WinRT/UWP? No, it's still a catastrophic failure today if you look in terms of the smartphone marketshare. Those descriptions in Wikipedia accurately describe the situation of UWP.

Now today we all have to agree that at the current point in time, 7-8 years after the release of WinRT/UWP, it's now too late to cancel UWP, but this means we're again falling victim to the "Plan continuation bias" and aversion to loss of sunk costs.

So what can reasonably be done to rescue the situation? We cannot rescue the situation by cancelling UWP, even though it definitely should have been cancelled years ago. What we can do is this: Accept the gigantic damage that was done by WinRT, but don't cause any further damage, and make changes to the project's procedures/policies. This means, stop repeating/continuing the same catastrophic mistakes of WinRT. For example, stop downgrading such large amounts of managed code to unproductive old unmanaged "native" code. The delay in reaching true beta status is already very large -- why make the delay even worse?

The "Plan continuation bias" / sunk cost mistake continues if DataGrid is downgraded to unmanaged "native" code. When a catastrophic mistake such as WinRT/UWP is made, it becomes much worse when this same mistake is repeated again and again and again. In order to limit the damage, it's necessary to stop repeating the same mistake. It's well-and-truly time to learn from the catastrophic failure of WinRT and start applying bandages to stop the ongoing blood loss.

Converting DataGrid to unmanaged code is the same as going to a library and borrowing all of the best project management books from the best authors with the most knowledge/experience, and then throwing all these excellent management books in a bonfire and watching them burn.

@verelpode I'm curious what your point here is with your two very large posts wrt DataGrid. I'm personally not really understanding what the above feedback specifically is wrt improving an OOB DataGrid control. The only thing I got was you're worried it's a waste of time to convert it to native code, but that doesn't address those who uses WinUI from C++. You're still free to use the current managed implementation if you're ok with the overhead of loading the managed runtime. Everything else seems to be about WinRT and the UWP app model, neither of which really applies to WinUI, as it's getting completelyunbound from that with v3.

@dotMorten -- the reason why I wrote extra detail in those messages is because if I don't explain the problem adequately, then people won't understand it. But sadly now I see that the extra detail failed and it was still not understood anyway. That's very frustrating. This is the reason why many people don't even bother writing any feedback at all, because they believe it's pointless to try to explain these kinds of issues to people, and even if the message is understood successfully, then it's human nature to shoot the person who delivers the bad news, so better to say nothing at all, or just "politely" smile while thinking the opposite.

as it's getting completelyunbound from that with v3.

This v3 unbinding doesn't prevent repetition of the same mistakes. The "Plan continuation bias" still exists.

Go to the home page of Microsoft:
https://www.microsoft.com/en-us/
Now scroll down the home page until you see Windows Phone. Oh! Look at that! We've reached the end of the home page and Windows Phone is not mentioned ANYWHERE on Microsoft's home page! What does this mean? It means, wake up. It means that UWP was a catastrophic failure as I said. It means, it's important to stop repeating the same mistakes that led to the failure of UWP. It means, change the plan in order to rescue and recover from the disaster.
It would be a management mistake if WinUI and DataGrid continue to repeat the same mistakes as in UWP's failure.

"In May 2016, Microsoft gutted its mobile business, .... In 2017, Microsoft executive Joe Belfiore revealed that Microsoft had ceased the development of new Windows phones and new features for Windows 10 Mobile, citing the losses in market share and lack of app development."
-- https://en.wikipedia.org/wiki/Microsoft_Mobile

Ana lists 5 points to provide feedback on wrt DataGrid. Which of those points are you commenting on? I guess that's the bit I don't get from what you're writing. UWP doesn't satisfy the need for everyone, but WinUI3 doesn't dictate using the UWP app model, and you seem to be mostly against UWP? So you should be fine there.

You mentioned DataGrid shouldn't continue to make the same mistakes it made. So which are those mistakes specifically wrt the existing DataGrid, and how do you suggest they should be corrected? (apart from you don't want it implemented in C++ for some reason)

@dotMorten

Ana lists 5 points to provide feedback on wrt DataGrid. Which of those points are you commenting on?

The part where I quoted Ana at the start of my message. I am commenting on the part of Ana's message that I quoted at the beginning of my message.

WinUI3 doesn't dictate using the UWP app model

That's unrelated to my message. WinUI 3 being unbound and available via nuget package is irrelevant to the question of whether WinUI 3 continues the same management mistakes that led to the failure of UWP and Windows Phone and Microsoft's multi-billion dollar loss.

how do you suggest they should be corrected?

The 6 bullet points at the end of my earlier message. The second bullet point (scripting) relates to WinUI and UWP in general, but doesn't relate to DataGrid. The first bullet point is the most important one if you're asking specifically about DataGrid.
I also wrote: stop downgrading such large amounts of managed code to unproductive old unmanaged "native" code. The delay in reaching true beta status is already very large -- why make the delay even worse?

@anawishnoff wrote:

we are interested in graduating it to a native WinUI control

"graduating it to a native WinUI control" constitutes practically a continuation/repetition of some of the same mistakes that led to the "losses in market share and lack of app development" mentioned in Wikipedia:

"In May 2016, Microsoft gutted its mobile business, .... In 2017, Microsoft executive Joe Belfiore revealed that Microsoft had ceased the development of new Windows phones and new features for Windows 10 Mobile, citing the losses in market share and lack of app development."
-- https://en.wikipedia.org/wiki/Microsoft_Mobile

Why should DataGrid continue along the same path that destroyed Microsoft's mobile business?

@verelpode

WinUI 3 continues the same management mistakes that led to the failure of UWP and Windows Phone and Microsoft's multi-billion dollar loss.

I do not work for Microsoft but I am curious why you say WinUI is making management mistakes.
From what I see the very fact that WinUI is being open sourced and everyone gets to contribute to conversations and decisions is actually helping define what WinUI is and should prevent mistakes from happening.
You mention that the DataGrid is continuing along the same path as mobile yet nowhere in the pitch did I see it mention mobile. Perhaps you can keep feedback directly to what this issue is discussing.
If you feel there are mismanagement steps with WinUI then perhaps you can create a separate issue with your concerns but I really don't think that your comments have anything to do with the DataGrid control.

@verelpode please keep your feedback here on-topic. If you have concerns about WinUI or UWP at large, please start a new discussion topic or contact me directly (email me or DM on twitter). Or you might consider discussing on an existing topic like #717 or #1531.

You shared concerns about DataGrid getting re-written in C++, but actually the original proposal didn't mention anything about that. @anawishnoff is trying to collect feedback about the DataGrid feature set. Implementation-wise, if it makes the most sense to keep it in C#, we would do that (and it could still be callable from C++ if we did it as a WinRT component).

@jevansaks -- My feedback was on-topic, but it's human nature to shoot the messenger who delivers the bad news. Your response makes me sad and disappointed. OK, I'll stop trying to help, because my assistance is unwanted because it's too honest and direct and touches on painful issues that are too painful to acknowledge and solve (the catastrophic failure of WinRT raises too many emotions and so it's easier to erase it from memory and continue the same old original WinRT plan as if the disaster never even happened). I'll exit this discussion and not participate any further in DataGrid's development because continuing to speak honestly and directly about the real problems will only annoy people.

@verelpode No one "shot the messenger who delivers the bad news" here. @jevansaks invited you to open a new issue to share your broad concerns about UWP/WinUI/WinRT in this repository. This issue really is only about the DataGrid and while indeed one of your concerns was about DataGrid, the vast majority was about UWP/WinUI/WinRT in general. I'm sure if you will look at this discussion again, you will see that the WinUI team is just asking you to keep this issue focused solely on the DataGrid proposal and to open a new/use an exisiting issue for your broader concerns about the platform.

The concerns you mentioned can be the basis for an interesting discussion involving both the WinUI team and the community, but this particular issue isn't suited for such a discussion.

@anawishnoff
I am pretty sure that the Microsoft Pivot Viewer Control was not html. Please look back at it. The ability to visualize large sets of data using something like that was something that we have wanted to do at times. It was available in Silverlight I think. https://www.microsoft.com/silverlight/pivotviewer/default# It used Deep Zoom for it functionality. Adding Deep Zoom capability to WinUI 3.0 would be fabulous! Not really the Datagrid, but a Data Display control. There are lots of "abandoned" ideas from the early days of WPF like Deep Zoom that never made it into a production WPF control that would be wonderful to bring back to life in WinUI 3.0 over time. Heck go get Dr. WPF out of the basement and get him posting again!!! We need him back. We need to start a movement. BRING BACK Dr. WPF !!!!! Where have you gone? Dr. WinUI!!!

@PaulMontgomerySP sounds like you should open a new issue to discuss the Pivot control. Feel free to reference the previous discussion that was had about it from the Windows Community Toolkit here: https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/770

The selection changed event fires for each row I move to with the keyboard.
It would be nice to have an event solely for a mouse click or cell tap, instead of only the selection changed event.

The selection changed event fires for both click, and keyboard. It would benefit greatly to have a event solely for clicking.

@Going-Gone I'm curious what the use case for that is? Why do you need to know the difference? Also can't you use the tapped event?

One limitation I just hit with the UWP Toolkit's DataGrid is the DataGridTemplateColumn has a CellTemplate, but it doesn't have a CellTemplateSelector (and the same missing for CellEditingTemplate). It would simplify adapting the UI in each cell to the data using the selector approach, rather than having to do this with an extra level of UI controls below it to handle that.

Please also make it possible to select rows not only in a consecutive order like I have explained in detail here:
https://github.com/duke7553/files-uwp/issues/276#issue-520060100

In no particular order of things that are often requested by clients that a grid should support

1.Ability to save, load and build filters. Eg filter to linq expression, filter to SQL query, filter to expression tree and the reverse. Example - https://querybuilder.js.org/demo.html

  1. High speed real time data capabilities, performance matters. Sub 1ms refresh rates for trading application vs > 1million rows have different performance considerations.
  2. Ability to specify sort order, eg i. sort high/low, ii. sort low/high and iii. no sort or i. sort low/high, ii. sort high/low and iii. no sort
  3. Excel-like filtering
  4. Ability to apply css formatting to cells, conditional formatting
  5. Ability to easily save/load grid settings, eg filters, column widths, sorting etc
  6. Scrolling which works, eg doesn't reset after data update, smooth.
  7. Data Collection events should have options to fire events after loading ranges rather than individual objects. Eg I believe ObservableCollection requires subclass to prevent INotifyPropertyChange firing for each individual object added.
  8. Better events for when data is loading/loaded, data load started, data loading, data loaded especially if using async loading.
  9. Grids are often linked to other controls such as data filters, range selection, crossfilter (eg https://github.com/dc-js/dc.js), charts, pivot tables etc
  10. Smart sorting which handles alphanumeric data, eg sort order ABC11, ABC12, ABC111 instead of ABC11, ABC111, ABC12
  11. Unlimited levels of hierarchical grids, eg https://docs.telerik.com/devtools/wpf/controls/radgridview/hierarchical-gridview/hierachy-overview

Useful resources: - Design Better Data Tables
https://news.ycombinator.com/item?id=21460966
https://uxdesign.cc/design-better-data-tables-4ecc99d23356

I won’t be able to Bind to the Columwidth from the Header directly. In WPF I must use a BindingProxy Object in that case.

Convenient dynamic resizing of the active row for easier editing.
Full control of context menus in edit mode.

Hope it support CellDecorationStyleSelector as in Telerik.

Accessibility!
Mentioning it so it's documented, but this control needs to be fully accessible.
The current toolkit version has some limitations in this area: https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/3400 & https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/3079
Also, while the Telerik RadDataGrid has some great features it seems to not support accessibility.

With Microsoft's big push for D&I, I'm surprised that the needs for all controls to be fully accessible isn't specified as a requirement everywhere.

Perhaps this is already possible, and I just don't know how to accomplish it yet... but how about: custom row or cell styling?

The ability to target a specific row, alter the background and the text color would be great.

As compared to the WCT UWP DataGrid:
1) Performance
2) More built in Column types (I assume that these have better performance than template columns)
3) Ability to hook mouse events per cell, i.e. tap, right tap, and hover, (or pointer down or whatever)
4) Keyboard events per Cell
5) If (3) is not workable, we could emulate if we had hit testing functionality
6) Performance

How many people would raise an objection if WinUI DataGrid abandoned the feature where end-users are able to edit cell values inline/directly inside the DataGrid?

Does anyone remember VB6? The VB6 DataGrid supported Edit, Delete and AddNew out of the box. Add was available as a blank row automatically added to the end of the list. Complete the row and another blank row appears.

A DataGrid should have the option to support data entry, even if most devs prefer this feature to default to off.

In porting a VB6 app to UWP we had to write our own data grid to support add/edit/delete.

It does seem that most who contribute here are WPF/Xaml folks, this is two cents worth from someone who isn't a xaml guy.

I use DataGrid controls a lot in my software. Editing is place is important! Some of my wishes/pain points are:

  1. Ability to customize the context menu when in edit mode.
  2. Better performance and more control when autosizing columns. I want the user to be able to control sizes if necessary but mostly not need to. I don't want column sizes to constantly change, but I want them to somehow be based on data without having to measure a million rows' worth of data.
  3. When editing, I want to be able to click on a different control/button that does something to (or with) the data being edited without ending the edit. (This would be less necessary if #1 were implemented - though still useful.)
  4. the current way exceptions are handled using the DataError event is rough. (Sorry, I'm having trouble being specific on this, but I know it's caused me pain several times in the past.)
  5. Built-in auto-scrolling capability would be nice: http://stackoverflow.com/questions/2567809/how-to-autoscroll-a-datagridview-during-drag-and-drop
  6. Ability to display a "watermark" indicating when the data is "dirty" (see BetterGrid for some additional useful enhancements to DataGridView.
  7. Ability to abandon a row (without a validation error) when the required "key" cell is left blank.
  8. Built-in ability to display no image (instead of a red X) for a user-added row. See: https://stackoverflow.com/questions/937919/datagridviewimagecolumn-red-x
  9. Allow for a check-box column to commit immediately when changed: https://stackoverflow.com/questions/11843488/how-to-detect-datagridview-checkbox-event-change

When is the alpha expected to be released? Will it be open to contributions? Trying to ditch an outdated data grid and really looking forward to this, especially virtualization feature.

Sorry for putting a very late input to this thread, but to me it is "new" ;)
_edited after finding out a bit more about how the control behaves_

In working with DataGrid toward making an explorer like interface for cloud drives, I found that determining the row and cell that is tapped may be a bit more complex than it "should" be (IMHO)

In my app's design, the rows represent files or folders (DriveItems). The detail view shows more details about the item.

I wanted to create an ability to click on a folder item, and have the interface jump over and create a list of those items, allowing navigation throughout the drive.

image

For instance, if I tapped on the item's "Parent" column entry, /drive/root:/Documents/Vital%20Documents here, the interface would reset to that folder and list the files there.

Though one can get a clicked event for the cell, that event doesn't seem to have the context for the handler to determine the cell that was tapped (row, yes, but not column), and I'm not sure that currently the control would allow me to have both the cell tapped behavior AND the automatically open details behavior (still investigating what I might call "hacks" that would allow that, but we have to remind ourselves that when designers start to override the control's normal functioning, especially not behaviors that are documented, they run the risk of having the design broken by changes in the control's behavior.

All this said, DataGrid seems to support my scenario by having the event that currently returns the DriveItem as CurrentItem, should also include a CurrentColumn that would be the entire DataGridColumn object that was clicked within, through which it would be possible to extract the column name. I do realize now that we have the CurrentColumn object we can investigate from the event, so, although I'd like it better as the event args, this should work.

Also, more stringent control of the details behavior might be that the details would only be auto-expanded based on clicking on one particular column, instead of expanding whenever one clicked anywhere in the row.

Maybe the base class of the DataGridColumn object could have a ExpandDetails property that can be set to true by default for each column, which would mean that particular column being clicked on causes the row to expand. Others where the property is false would not be.

In my design, for instance, the first column is the item type, as in File or Folder, or Image or Photo, Audio, etc. I might envision setting that column up to be the only one to cause the auto-expand behavior, and then a click on the Path column could cause the "get a list of that path" behavior I described above.

As for sorting, it would seem logically important to implement enough control to allow designers to get multi-level sorting. I haven't done investigation to determine how the current control might support this through hooking/overriding events and callbacks, but it doesn't look straightforward.

Finally, I know you are well aware of this, but (even as I'm asking for more functionality), let's PLEASE avoid trying to add a bunch of complex behaviors that users can implement themselves on top of the DataGrid. Among these that I wouldn't implement in DataGrid are any which have to do with externally storing filters or sorts, etc. I would also avoid making this control into an excel clone.

-thanks, great work!
-e

Sticky groups: when browsing datasets with large groups there should be context about which group (or groups, i.e. breadcrumb) is being viewed. This seems like an essential usability feature for all hierarchical list-based views: grouped list views, datagrids and tree views.

I would build the new DataGrid control on top of the new WinUI ItemsRepeater control. And that control exposes its ItemsSource as an Object:
Object ItemsSource { get; set; };

@RBrid Coming back to this ~1 year later. I realized that ItemsRepeater, although it has an object ItemsSource, doesn't actually have built-in support for the following interfaces necessary for working with virtualized data sources:

  • ISupportIncrementalLoading
  • IItemsRangeInfo
  • ISelectionInfo

-What about getting a MVP in there now so we can use a Datagrid from c++.

Was this page helpful?
0 / 5 - 0 ratings