How can I virtualize a "datagrid like" Control Horizontally and Vertically on XAML/C# (Windows 8.1 - WinRT)
Asked Answered
G

2

10

Problem

I'm trying to create a "datagrid like" control on a Universal App (WinRT).
This control has to show lots of elements (Cells) but only has a small View-area, so it's a perfect candidate for Virtualization, which it definitely needs.

How can I have Virtualization both Horizontally and Vertically for such a thing?

example "table like" control with a View Area

What I tried (One-Direction Virtualization)

I have tried using both the ListView, GridView and ItemsControl. I obviously managed to have Only Vertically or Only Horizontally Virtualization with those.

The most important thing I had to do to achieve One-Direction Virtualization and have it look like a table was changing the ItemsPanel of any of those (ListView/GridView/ItemsControl) to something like this:

<ScrollViewer           
       VerticalScrollBarVisibility="Auto" 
       HorizontalScrollBarVisibility="Auto" 
       HorizontalScrollMode ="Auto"
       VerticalScrollMode ="Auto"
       ZoomMode="Disabled"
       ViewChanged="DataGridView_OnViewChanged"
       Width="700">
    <ItemsControl 
            VerticalAlignment="Top"
            HorizontalAlignment="Left"
            ItemsSource="{Binding Cells}"
            Width="{Binding DataGridWidth}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <ItemsWrapGrid MaximumRowsOrColumns="{Binding NumberOfColumns}"
                            VirtualizingStackPanel.VirtualizationMode="Recycling"
                            ItemWidth="{Binding CellWidth}"
                            ItemHeight="{Binding CellHeight}"
                            CacheLength="2.0"
                            VerticalAlignment="Top" 
                            HorizontalAlignment="Left" 
                            Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        ...
    </ItemsControl>
</ScrollViewer>

Note: "VirtualizingStackPanel.VirtualizationMode" and "CacheLenght" are not really necessary in there. But notice that I'm setting the Width on the ScrollViewer and the ItemsControl. I think that's the culprit in making this Virtualized only in one direction. Because I'm giving the ItemsControl enough room to display the items. Problem is, it's the only way to make the MaximumRowsOrColumns work and achieve a "DataGrid like" control.

This solution starts becoming sluggish/broken at roughly 100 x 100 elements because even if it's only displaying 10 rows, it's still 10x100 Cells to draw.

The Cells all have the same look and feel and therefore share the same DataTemplate which should help getting a solution.

I can use any Control, I only mentioned ListView, GridView and ItemsControl because they were the ones more obvious to me (to solve this problem).

Any ideas on how to achieve Two-Direction (Horizontal and Vertical) Virtualization with a "DataGrid like" control on Windows Universal Apps with XAML/C#?

Note 2: WPF solutions likely won't work with WinRT XAML/C#. Please check that before posting a WPF solution.

Goldina answered 1/4, 2015 at 18:44 Comment(3)
I haven't gotten to work in RT yet as much as I'd like to sound competent but is there no DataGrid already available you can just strip the column/row headers off of?Furcate
No , there's not such thing unfortunately. There's a Grid obviously but it's for layout, not data (and has no virtualization capabilities) Controls: link PS: I actually need the Headers, I just simplified my problem. :)Goldina
Looks like there's a few available from the vendors like Teleriks that are passing certification but I don't know that it calls for that, I'll swing back to this if I have more time since I'm sure it will come up for too at some point. In the meantime +1 and wish I could be more helpful lol.Furcate
S
1

I haven't done this, but found a few interesting articles:

1) Your grid is located in the ScrollViewer, how about trying to use attached propery like VirtualizingStackPanel.VirtualizationMode?

Link: https://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.virtualizationmode%28v=vs.110%29.aspx

2) If previous doesn't work for you, i guess you can write your own virtualization mechanism by using Incremental virtualization article ( i really think they can be used for this ).

Link: https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh780657.aspx

Sainted answered 8/4, 2015 at 6:32 Comment(4)
#1: Tried it, does nothing. #2: Incremental Virtualization only works with ListView/GridView and I think I can't use those on my situation (I know I didn't explain that). Anyway my biggest problem is not the ViewModel Virtualization, it's the View Virtualization.Goldina
I know this answer is not the best. I just updated it with more info. Normally the ItemsWrapGrid would virtualize every item. Problem is I'm setting the Width on the ItemsControl, so it doesn't virtualize them, because it thinks they are visible. I have to do that to make the MaximumRowsOrColumns work and achieve a "table like" control.Goldina
So you say, if you do not add exact size - all works fine? You do some calculations when set MaximumRowsOrColumns based on the width of the columns you set? Why not using ActualWidth/ActualHeightSainted
If I don't add the exact Width on the Items Control, the Virtualization will work because the ItemsWrapGrid will ignore the MaximumRowsOrColumns and actually "Wrap the row" at the end of the ItemsControl Width, so I no longer have an Horizontal Scrollviewer. But the "datagrid" no longer makes sense, because cells from row 1 get pushed to row 2 and so forth. (did this make sense?) ActualWidth doesn't have a setter, how do you want me to use it?Goldina
I
1

I'd suggest a completely different approach: instead of putting your large amount of data into any form of UI control, you simply constraint the GridView (or whatever control you prefer) to the size of the view area. When the user "moves the over the data" she effectivly moves the hidden area over your view area. That means you just change the content of the cells within your fixed view area accordingly. For instance, when the user moves the data 10 columns to the right you shift the content in the view area by 10 columns and fill up the left-hand side with 10 fresh data columns.

You'd have to keep the data for the hidden area in a table-like data structure so that it is easily accessible by row/column.

In terms of implementation I'd make the viewable data a property of the view model. The GridView binds to this property. When the user "moves over the data", you simply copy data from your table-like data cache to this view area property in the view model.

I have little information about your actual use case and the expected look & feel of your control, so my sugestion may be a long shot. However, given the enormous amount data you have to display it may be worth a try.

Isonomy answered 11/4, 2015 at 1:5 Comment(2)
I've removed removed link to DataGridView. Hoewever, I'd apprecciate if you read my post to the end and don't stop after the first paragraph. Thanks..Isonomy
Unfortunately I know why HighCore commented that way. :) Although I don't like that approach it could work if the app only had mouse/keyboard input/interaction. That's not the case, the app will be used mostly with touch input (mouse and pen being an extra). Not sure if you are aware, but with "touch scrolling" that approach won't be fast enough. Mostly because of the way touch scrolling works. I would expect it to be far worse than my current solution. Thanks for trying anyway :)Goldina

© 2022 - 2024 — McMap. All rights reserved.