Live refresh for RadGridView when sorting/filter/grouping

1 Answer 283 Views
GridView
alex
Top achievements
Rank 2
Bronze
Iron
Iron
alex asked on 31 May 2023, 07:21 AM | edited on 02 Jun 2023, 03:55 PM

Hello,

After reading multiple questions in this forum regarding why the RadGridView is not refreshing when an existing item is updated, I am developing the refresh mechanism. I tried your suggest (calling CollectionChanged.Reset) but this solution is not good for us because when we call CollectionChanged the RadGridView is updated and also a lot of elements are drawn in a screen (thousand of elements and it cost a lot of performance).

So my solution is using a timer with refresh interval of 1 second which will refresh all the subscribed RadGridViews.

* I used WeakRefereces to avoid Memory Leaks.

In the distpatcher timer I do the following code:

if(radGridView == null || !radGridView.IsVisible) return;

var isRefreshRequired = radGridView.GroupDescriptors.Count >0 || radGridView.FilterDescriptors.Count>0 || radGridView.SortDescriptors.Count>0

if(isRefreshRequired)

{

   var collectionView = CollectionViewSource.GetDefaultView(radGridView.ItemSource);

   collectionView.Refresh?();

}

 

As mentioned, this code guarantees that only the view (RadGridView) is refresh and not the other elements of the SourceCollection.

I need your help with the following:

1. Only when there is a group and I scrolled down, after refresh the grid jumps to top (I couldn't reproduce when sorting or filter is enabled).

2. There is any good way to really know if the RadGridView is shown on screen (maybe it is visible but hidden in other tab), I need a method with fast access because I may check around 15 grids every second and I want to refresh only the required grids.

3. I tried to refresh the radGridView.Items instead of radGridViewItemsSource.
I expected this to work beause Items holds the items after grouping/filter/sorting. Unfortuneatly ,it doesn't work.

There is any way to refresh your internal view instead of the SourceCollection view that is bound to ItemSource?

The problem is that CollectionChanged on the view, triggers other code on my side that it will be good to skip for this case.

EDIT:

* I figured out that if I have a grid with 500 elements with two groups of 250 rows and one group is expanded then the application is almost freeze, the refresh is killing the performance. I think that my solution is better than Collection Reset so I don't know how to solve this :(

* Regarding point one, I think that the grid jumps because the Panel Unit is set to Content. I can't switch to Pixel because it will cause bad performance.

* I noticed that you have the method Reset for GroupDescriptors and SortDescriptors, the performance is the same. I taught that you maybe manage an internal caching and have some improvements there.

1 Answer, 1 is accepted

Sort by
0
Vladimir Stoyanov
Telerik team
answered on 05 Jun 2023, 07:49 AM

Hello alex,

Thank you for the shared information. 

I will start by saying that one of the options for reevaluating the data operations is to use that approach suggested in the following article: Edit an item outside RadGridView. Also, note that it is expected that the RadGridView will be redrawn when the CollectionChanged is called, since this indicates that a full reset of the data engine is needed.

That said, I will go straight to the listed points:

1. You can check out the PreserveScrollPosition SDK example. It demonstrates how to restore the scroll position after the collection is reset. Note, that you may need to adjust the implementation from the example to support a grouping scenario. 

2. There isn't a specific way to determine whether the RadGridView is on screen. You can check out the following thread, where a similar question was discussed in general for a WPF control: In WPF, how can I determine whether a control is visible to the user?

3. With the current implementation of the RadGridView, the options for ensuring the reevalution of the data operations are the ones listed in this article. We do have an item in our feedback portal to provide an option for data operations to be reevaluated on property changed. You can vote for it and follow the item to get notified for any updates. 

Regards,
Vladimir Stoyanov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

alex
Top achievements
Rank 2
Bronze
Iron
Iron
commented on 05 Jun 2023, 07:36 PM | edited

Thanks you Vladimir, regarding point 3, I voted and also I've seen a lot of requests in other threads.

We will appreciate if you decide to add this functionality.

Please take a look at my code in the question and the first asterix in the EDIT section. We are facing poor performance only when grouping. What can we do about it?

I read ALL your posts, for example:

https://www.telerik.com/blogs/fast-real-time-data-update-for-your-silverlight-and-wpf-applications

We have grids of 2,000-5,000 elements and 20-50% of them are updated EVERY SECOND. While grouping by Last Update Time Column I prefer to refresh the view, this will trigger collection reset (first option in the link). This is better than calling Replace for every item on every second (less notifications are triggered and with Virtualization only 60 rows should be recreated in the UI). Please provide a better solution.

We are using Office 2013 Black Theme. Maybe can you offer some lightweight templates? I saw your other posts but your examples are not supported by our theme.

I need a starting point to fix the performance issue on refresh. The grid is slow and I don't think that it is happening because of my implementation.

As mentioned in the original question, the issues are hapenning already with two groups of 250 rows.

We didn't test it already with toushands of rows as required in the final solution.

Vladimir Stoyanov
Telerik team
commented on 07 Jun 2023, 11:00 AM

Generally speaking, the option of replacing the modified items should be faster than resetting the collection. Note, that the suggested approach would be to only replace the items in the collection that were modified. You can implement some logic to collect the items that need to be updated and update them once the view needs to be refreshed. 

I am attaching a sample project that demonstrates how the view can be refreshed by replacing some of the items in the collection bound to the RadGridView ItemsSource.

On a side note, you can also take advantage of the lightweight templates that the RadGridView provides. You can also take a look at the Tips and Tricks article for more suggestions for improving the performance. 

alex
Top achievements
Rank 2
Bronze
Iron
Iron
commented on 09 Jun 2023, 07:23 PM | edited

Thank you Vladimir,

I appreaciate your help, I will take a look.

Generally speaking, in my application all the items are changed every second because every element have 30 properties (columns) and at least one of them is changed. I am refreshing the view only if there is any sort/filter/group. I updated the code to refresh only if the property that is grouped changed but what will happend if I have a column of timestamp that is refreshed every second for 2000 elements? I need a solution for this particular case. After founding a solution for this, it will solve all other cases so that is the reason that I don't really care refreshing even if the item wasn't changed (most of the cases all the items change).

The grid is already bound to all properties and it will be easier if you replace the item when some new property is enabled.

It could be easier to make a specific solution for one grid when I know the DataContext but I am looking for a generic solutions for all grids. Every column can be bound to children of children in the element or RelativeSource to some parent. There are so many points to consider that the easier way is to refresh every 5 sec only if some Sort/Group/Filter exists. Maybe a light template will make it faster. Again, even implementing your solution, I tested with the Timestamp column and it is extremelly slow when every row changes. The bottleneck is the redraw of the rows when all rows changed.

I will let you know about additional test I am trying.

Please, make an internal discussion with your team, I am really sure that together we can think about some easy solution, you have access to code that I can't reach.

A lot of customer needs that capability and if you add this with some flag (false by default) you will be proud of giving a better product.

alex
Top achievements
Rank 2
Bronze
Iron
Iron
commented on 12 Jun 2023, 06:56 PM | edited

UPDATE:

Using the lighweight templates significantely improved the performance. Now I can refresh the grid every second and I can select an item or use the scrollbar (with the default templates the grid was frozen when the refresh rate was less than 3 seconds).

Can you please explain the following:

1. What is the difference with the default templates? what features I don't have because of this change?

2. Why the lightweight are not the default? why do we need two styles?

3. I have a project only with styles. This project have references to nugets (no xaml) like Controls, Controls.Input, Themes.VS2013, etc. The project is loaded at the application startup.

I have another 15 projects on my solution with references to xaml nugets and this works as expected.

Can I have any problem with this configuration?

Why the NoXaml is required only in the project with the styles (I have styles based on Core styles). I can't change the other projects because they are used by many teams and I don't know about the impact.

* I saw in your tutorial that the nugets can't be mixed and it can cause problems, but why? I added the nuget to the theme so I have all my styles and only those styles are used even if other styles are loaded in xaml nuget.

I think that it works beause I have the reference to the Theme as described here (I have Visual Studio 2013):

Get the .xaml files with the control styles and templates.

Reference the theme dll from the /Binaries.NoXaml/ folder - for example Telerik.Windows.Themes.Office_Black.dll. The theme dll contains ResourceDictionary files with the styles for the controls.

 

Am I right?

Vladimir Stoyanov
Telerik team
commented on 13 Jun 2023, 11:01 AM

I am glad to hear that using the lightweight templates has made an improvement on your end. Given that the most amount of time is spent in rendering the rows, the best approach for limiting this time is to reduce the amount of visual elements that need to be drawn (which the lightweight templates do). 

To answer your questions, the GridViewRow lightweight template does not support the row details and hierarchy features. The GridViewRow/GridViewCell lightweight templates also lack the elements required for displaying validation errors, however there are alternative lightweight styles, which also include this feature. The fact that there are some missing features is the main reason why these styles are not used as the default ones. Additionally, switching to these styles as the default ones will be a breaking change. 

As for the Xaml vs NoXaml dlls or Nugets we don't recommend mixing them, since they are used with our 2 different theming mechanisms. Xaml dlls are used when theming with the StyleManager and NoXaml dlls are used when using implicit styling. The difference between the two is that the Xaml dlls contain all of the xaml for the controls in them for all of the themes that we provide. The NoXaml dlls are lighter because they don't contain any xaml. That is why with this theming approach (implicit styling) you also need to reference the theme dll of your choice (depending on which theme you want to use).

To summarize, you should choose which theming approach you want to adopt and use the corresponding type of Nugets (StyleManager -> Xaml, Implicit Styling -> NoXaml). I want to note that there aren't any differences in the code of the controls between the two (the only difference is that the NoXaml ones lack the ControlTemplates/Styles, which are in a separate theme Nuget).

We recommend using the NoXaml + implicit styling approach. The main benefits being the smaller size of the dlls along with an easier process for modifying the ControlTemplates (you don't need to extract all StaticResources used in them, since they can be merged from the theme dll).

alex
Top achievements
Rank 2
Bronze
Iron
Iron
commented on 14 Jun 2023, 07:48 PM

Thank you Vladimir for your detailed response.

Everything was clear. I will follow your instructions.


Tags
GridView
Asked by
alex
Top achievements
Rank 2
Bronze
Iron
Iron
Answers by
Vladimir Stoyanov
Telerik team
Share this question
or