🧪 Modern/Lightweight 'DataGrid' - Introducing DataTable #415
Replies: 27 comments 44 replies
-
@michael-hawker With the proposed solution, would that mean that resizing columns can only be done in the header and not in the ListViewItems? (Which I think is totally fine.. and inline with what the OS does 😊) |
Beta Was this translation helpful? Give feedback.
-
Ah, forgot about these two Uno Issues for WASM:
Could pose a problem for this solution working with Uno, at least on Web Assembly. |
Beta Was this translation helpful? Give feedback.
-
Hmm, if this all works, we could maybe extend the |
Beta Was this translation helpful? Give feedback.
-
Initial prototype looks promising, have the initial panel-test for In branch: https://github.com/CommunityToolkit/Labs-Windows/tree/llama/datatable Need to decide if we want to keep this interop-hybrid compatibility with |
Beta Was this translation helpful? Give feedback.
-
This really looks promising. I like that it has virtualization. Do the headers remain in place when scrolling like they do on a DataGrid? That's something that regular repeater/items controls don't do by default. Resizing would also be nice :) This page originally had a DataGrid, but I removed it for all the reasons you know. There's a lot of datatemplateselector cruft happening right now to handle the display of different message types on the right. That (or some equivalent code alter) would need to be there regardless of control used. Pete |
Beta Was this translation helpful? Give feedback.
-
Well, have very initial prototype together (ListView padding of item throws the alignment of headers a bit off, to do item): Has basic structure using new Makes defining columns super simple, but familiar/similar to
Still to be explored:
|
Beta Was this translation helpful? Give feedback.
-
This is nice solution between DataGrid and an ItemsRepeater. I do like that each cell does not need its own cell template. I also like that I can add borders to cells. One request. This request isn't a deal breaker. I have a grid with buttons in the rows and on the button click I need the context of the row. DataGrid's args was the object the button was clicked on. With an ItemsRepeater I need to declare the context in each button. Example. The click handler of the two buttons needs to know the object it was clicked on. DataGrid did this automatically. In an ItemsRepeater I need to do the following in XAML.
The above solution isn't terrible. But, might not be tried if the person is not versed in XAML. |
Beta Was this translation helpful? Give feedback.
-
Something things that would be nice for our project if possible:
|
Beta Was this translation helpful? Give feedback.
-
What about row/column data direction? The |
Beta Was this translation helpful? Give feedback.
-
Just to play devil's advocate, and also because it's not entirely clear to me: why would it not be viable to instead improve |
Beta Was this translation helpful? Give feedback.
-
Can't remember where the Anyway, had to file microsoft/microsoft-ui-xaml#8451 as Surprisingly, did kind of what I expected, but seems promising. Think would want to have the tree part be buffered by the first column as in the example image/proposal in the WinUI repo for a 'TreeList' here: microsoft/microsoft-ui-xaml#260 That would make it easier to manager the indentation level in one spot. First step is probably understanding the size of the contents of the rows to size the columns though, haven't done that coordination in the prototype yet. Then this would need an extra bit for the TreeView around the padding on the left-side in relation to the rest of the panel/column sizes, which kind of needs to be adjusted between the ListView/ItemsControl containers anyway... All that said, seems like an interesting scenario to keep around to tinker with as things progress and see if it's possible without much extra work, as this would be a really interesting addendum to this methodology that I didn't originally think of (but should of)! |
Beta Was this translation helpful? Give feedback.
-
We're currently using a custom ListView + Header as a DataGrid alternative, over the years we've added a lot of functionality such as double clicking the headers to resize the column to fit the content. The logic in our app is complex and hard to scale as we add more columns, so we'll be very happy to switch to a Toolkit control. |
Beta Was this translation helpful? Give feedback.
-
Why not just do what WPF did and support GridView in a ListView.View type property. I'm pretty sure UWP can also switch a ListView to view as a table. If only a lightweight control is needed it doesn't make sense to me to write a new control and reinvent things here. |
Beta Was this translation helpful? Give feedback.
-
Have an initial test of resizing a column: DataTableColumnResizeTest.mp4Main issues to figure out are how columns should react with one another based on how they're configured. The current logic kind of uses the initial configuration to determine layout, so once that's disrupted, an altered strategy needs to be performed... This also ties into the notion of the 'Auto' sizing and figuring out how large a column wants to be based on its contents, as that's still left to investigate. The other question is should the items below be manipulated during the column resize or only afterwards (as in the video above)? Or something in-between with some sort of debounce? |
Beta Was this translation helpful? Give feedback.
-
Now that the WinUI 3 team made it clear that they are not (or won't be?) focused on a DataGrid control, the |
Beta Was this translation helpful? Give feedback.
-
Huzzah! May have auto column sizing working properly now... 😋 Do need to do some more testing, and check if it doesn't break virtualization... I have the connection more solidified between This was pretty straight-forward from what I had though, so still all very promising. And I have ideas for the last two issues to investigate before trying to merge the initial PR... |
Beta Was this translation helpful? Give feedback.
-
Thinking for column interactions:
Not sure if sizer for column should be to the left of the content in the column at the start or right-aligned at the end of the column... |
Beta Was this translation helpful? Give feedback.
-
I am assuming this new control is linked to the Design Guidance in the WinUI toolkit Will this end up using the new ItemsView control coming from the WinAppSDK File Explorer migration? |
Beta Was this translation helpful? Give feedback.
-
Hi! I was trying to apply the DataTable to the Hosts File Editor PowerToys (currently using a ListView) and found some issues:
Don't know if these are known issues but want to provide a feedback. |
Beta Was this translation helpful? Give feedback.
-
hi @michael-hawker
but i am getting an exception: |
Beta Was this translation helpful? Give feedback.
-
Attempting to test this out for replacement of DataGrid where no editing was necessary. Came to the conclusion that for most functionality this component is a great fit. Impementing a sorting mechanism is possible with the only drawback of no built in sort indicators. However I can see a shortcoming in the layout responsiveness, the "Cell" contents do not seem to apply Wrap or Ellipsis even if explicitly set on the TextBlock element. This shows up on resizing or even when the layout does not fit the text when initially filling the Item Collection. Quick check in the Visual Tree, and it seems like the TextBlock instances in the list elements do not get a width set from the layout, instead they just overlap |
Beta Was this translation helpful? Give feedback.
-
Not sure if this is the correct place to ask this, but am I right to assume that the DataGrid control won't be added to the 8.x and future versions of the Community Toolkit at all? And if/when the new DataTable control is added, will it be possible/easy for existing DataGrid users to switch? Probably not easy questions to answer, but we are using the DataGrid today, and are looking into how/if/when we will have to do a migration job. From browsing quickly through the discussion it seems like we might have to re-implement some features ourselves, but that won't be a showstopper if the controller as a whole is improved. Also, is there a status/plan for what happens to this DataTable in the near/far future? |
Beta Was this translation helpful? Give feedback.
-
Someone was looking at trying to do custom/dynamic column/data lengths for arbitrary dynamic tables (e.g. fetched from a database). So, still read-only display, but unknown composition at compile time. Seems the current code base makes this a bit tricky on a couple of fronts to support, was hoping that nesting controls could help with this sort of pattern: <!-- Parent Table Holder of our Row Items-->
<ListView ItemsSource="{x:Bind DataItems}">
<ListView.Header>
<!-- Set Header to another one for our dynamic columns -->
<ItemsControl ItemsSource="{x:Bind ColumnInfo}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- Use DataTable here as panel for our header -->
<controls:DataTable x:Name="TableHeader"
Margin="12,0,0,0" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Dynamically create DataColumns based on our column collection -->
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="x:String">
<controls:DataColumn Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ListView.Header>
<!-- Setup the rows themselves -->
<ListView.ItemTemplate>
<DataTemplate>
<!-- Need another container for our DataRow as a panel -->
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controls:DataRow TargetTable="{Binding ElementName=TableHeader}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Then use standard template for how we want to display each data item -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView> Unfortunately, ran into a number of issues:
If we 'updated' DataTable to be instead an ItemsControl (or even ListViewBase) itself, then we could provide it directly with an ItemsSource and ItemTemplate (with And being off ListViewBase, means we could potentially even try enabling drag-and-drop of the columns themselves, though cascading that down to each row to re-order its contents/layout would be interesting... though since we own the layout at that point, we just need to map the re-ordered column order to the original logical order of the collection. e.g. give each column its index, so even when re-ordered, we use that to get the index of the datarow's child to layout in the order we desire. Think that'd be the simplest, as just part of layout and doesn't actually need to mess with the visual tree. So, in the end I think we'd end up with something like: <!-- Parent Table Holder of our Row Items-->
<ListView ItemsSource="{x:Bind DataItems}">
<ListView.Header>
<!-- Now header is a 'super' DataTable -->
<DataTable ItemsSource="{x:Bind ColumnInfo}" Margin="12,0,0,0">
<!-- Dynamically create DataColumns based on our column collection -->
<DataTable.ItemTemplate>
<DataTemplate x:DataType="x:String">
<controls:DataColumn Content="{Binding}" />
</DataTemplate>
</DataTable.ItemTemplate>
</DataTable>
</ListView.Header>
<!-- Setup the rows themselves -->
<ListView.ItemTemplate>
<DataTemplate>
<!-- Need another container for our DataRow as a panel -->
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- Only note here is that DataRow may find its parent ItemsControl first, so we may need a 'skip' flag or the direct link option with an ElementName binding (as x:Bind won't work for that either)... -->
<controls:DataRow/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Then use standard template for how we want to display each data item -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView> |
Beta Was this translation helpful? Give feedback.
-
I can't use the right-click to copy and paste the Datagrid cell content in uwp, the right-click menu will appear instantly and then disappear. |
Beta Was this translation helpful? Give feedback.
-
IssueResizing the
at Package<PackageReference Include="CommunityToolkit.Labs.WinUI.Controls.DataTable" Version="0.1.240213-build.1640" /> References |
Beta Was this translation helpful? Give feedback.
-
It would be extremely nice to have a TreeTable control too. Where a line can have expandable subnodes. |
Beta Was this translation helpful? Give feedback.
-
There seems to me no movement on the DataTable... |
Beta Was this translation helpful? Give feedback.
-
DataTable
Initial PR: #418
Problem Statement
A lot of times app developers want to display a denser set of data, usually in a grid type format with multiple rows of items that have particular properties (e.g. an Id, Name, and Description).
Generally, this forces a developer to go from something more light weight like an
ItemsControl
orListView
to look at a full-blownDataGrid
control, even if they don't need all its capabilities for sorting, editing, selection, customization, etc...This adds a lot of complexity and overhead to an application where a more custom-built solution may do. However, it's hard to recreate this look without just nesting a bunch of
Grid
panels together.A main feature that a lot of these UIs do want to provide users though is the ability to resize columns. This is also hard to make work with a bunch of nested
Grid
panels without just moving to aDataGrid
as well.Inspiration
We see a lot of these patterns come up where a
DataGrid
is just overkill for the desired scenario, especially when:But there's no go-to for these scenarios, there's just, use lots of static
Grid
elements, make something custom, orDataGrid
.Proposed Solution
Imagine we had a way to coordinate the layout of all the items within an
ItemsControl
orListView
. We'll call this ourDataRow
, then we could have a singleDataTable
that we use as a Header in order to manipulate each column's size as a whole.This would also just work the same for an
ItemsControl
if row selection wasn't needed.Comparison to DataGrid
Benefits/Comparison over DataGrid:
ItemsControl
(static) andListView
(for selection)ItemsControl
itselfItemsStackPanel
(should containerize on the datatemplate, unclear if WCTDataGrid
supports virtualization)DataColumn
component).Limitations compared to DataGrid is that:
DataTemplate
for each item)DataCell
helper in future?)DataCell
helper in future)Technical Breakdown
First, why not
ItemsRepeater
? ItemsRepeater is powerful, but also more complicated to use and buildLayout
s for. This approach for the experiment gets us to a prototype faster and should be easier for developers to consume. It also allows for both usage with the light-weightItemsControl
andListView
and with row/container re-usage should still support virtualization those controls provide asItemsStackPanel
would still be used.I don't think a singular panel on the ItemsControl/ListView to handle this would work well. First, it would still need to know how columns are defined. Second, each item's data template still needs to be contained within some
Panel
anyway and theDataTemplate
is what takes the item and 'splits' it into each individual piece of data for a column.By using the fact we need a
Panel
in our template, we can use this to easily create this mesh of panels that are all tied to a single controller by walking up the Visual Tree. Ifx:Bind
could break out of the template that'd be more direct and performant, so resorting to run-timeBinding
anyway means we might as well just do this step for the developer vs. having to explicitly 'link' them together (unless there's scenarios to be used outside of an items based control, so it should still probably be supported if set by the developer as a short-cut to the logic).When initialized, the
DataRow
will walk and get the reference to theDataTable
to register itself. It will use the restrictions and current layout info from the Controller to lay itself out in a simple measure/arrange setup of theDataRow
.We will have to be wary of layout cycles and reducing creating extra ones as well. I'm hoping that when a controller column is resized, we can use the ending of that event to invalidate the layout all together and hopefully already know the specific sizes we desire each column to be. This is going to be the trickiest part of this setup and is going to require some investigation and fiddling with to understand and 'coordinate'. (Thus, the reasoning for the original naming.)
Open Questions
DataTable
,DataColumn
, andDataRow
)DataHeader
overDataColumn
as a name just in case or for a future revision?)API Reference Docs
SharedSizeGroup
References
Beta Was this translation helpful? Give feedback.
All reactions