Hello Telerik,
I have an issue when I try using your IsBusy property inside a grid.
Happens that the panel won't disappear. I tried using several of those "Loaded" events to make it happen manually (grid.IsBusy = false;), but then it won't even show at all.
I am using virtualization and infinite scrolling in my grid.
I just need a solution to hide the spinner when the data finish loading.
here is my code:
MainWindow.xaml
<
Window
x:Class
=
"TelerikVirtualization.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
Title
=
"MainWindow"
Height
=
"900"
Width
=
"700"
>
<
Window.Resources
>
<
Style
x:Key
=
"VitorStyle"
TargetType
=
"telerik:RadGridView"
>
<
Setter
Property
=
"AutoGenerateColumns"
Value
=
"False"
></
Setter
>
<
Setter
Property
=
"FilteringMode"
Value
=
"FilterRow"
></
Setter
>
</
Style
>
</
Window.Resources
>
<
Grid
>
<
Grid.Resources
>
<
DataTemplate
x:Key
=
"RowDetailsTemplate"
>
<
telerik:RadGridView
Name
=
"playersGrid"
Style
=
"{StaticResource VitorStyle}"
IsBusy
=
"True"
ItemsSource
=
"{Binding Children}"
>
<
telerik:RadGridView.ControlPanelItems
>
<
telerik:ControlPanelItem
ButtonTooltip
=
"Column chooser"
>
<
telerik:ControlPanelItem.Content
>
<
ListBox
ItemsSource
=
"{Binding Columns}"
BorderThickness
=
"0"
>
<
ListBox.ItemTemplate
>
<
DataTemplate
>
<
CheckBox
Content
=
"{Binding Header, Mode=OneWay}"
IsChecked
=
"{Binding IsVisible, Mode=TwoWay}"
/>
</
DataTemplate
>
</
ListBox.ItemTemplate
>
</
ListBox
>
</
telerik:ControlPanelItem.Content
>
</
telerik:ControlPanelItem
>
</
telerik:RadGridView.ControlPanelItems
>
<
telerik:RadGridView.Columns
>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding ID}"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding Name}"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding ParentID}"
/>
</
telerik:RadGridView.Columns
>
</
telerik:RadGridView
>
</
DataTemplate
>
</
Grid.Resources
>
<
telerik:RadGridView
Name
=
"RadGridView"
ItemsSource
=
"{Binding View}"
Style
=
"{StaticResource VitorStyle}"
IsBusy
=
"True"
RowDetailsTemplate
=
"{StaticResource RowDetailsTemplate}"
AutoGenerateColumns
=
"False"
>
<
telerik:RadGridView.Columns
>
<
telerik:GridViewToggleRowDetailsColumn
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding ID}"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding Name}"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding UnitPrice}"
Header
=
"UnitPrice"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding Date}"
Header
=
"Date"
DataFormatString
=
"{}{0:dd/MM/yyyy}"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding Discontinued}"
/>
</
telerik:RadGridView.Columns
>
<
telerik:RadGridView.ControlPanelItems
>
<
telerik:ControlPanelItem
ButtonTooltip
=
"Column chooser"
>
<
telerik:ControlPanelItem.Content
>
<
ListBox
ItemsSource
=
"{Binding Columns}"
BorderThickness
=
"0"
>
<
ListBox.ItemTemplate
>
<
DataTemplate
>
<
CheckBox
Content
=
"{Binding Header, Mode=OneWay}"
IsChecked
=
"{Binding IsVisible, Mode=TwoWay}"
/>
</
DataTemplate
>
</
ListBox.ItemTemplate
>
</
ListBox
>
</
telerik:ControlPanelItem.Content
>
</
telerik:ControlPanelItem
>
</
telerik:RadGridView.ControlPanelItems
>
</
telerik:RadGridView
>
</
Grid
>
</
Window
>
MainWindow.xaml.cs
using
System.ComponentModel;
using
System.Windows;
namespace
TelerikVirtualization
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public
partial
class
MainWindow : Window
{
BackgroundWorker worker =
new
BackgroundWorker();
public
MainWindow()
{
InitializeComponent();
DataContext =
new
ViewModel();
}
}
ViewModel.cs *(install Fody.PropertyChanged nugget to make have it compiling)
using
PropertyChanged;
using
System;
using
System.Collections.Generic;
using
System.Collections.ObjectModel;
using
Telerik.Windows.Data;
using
System.Linq;
using
System.Collections;
namespace
TelerikVirtualization
{
[ImplementPropertyChanged]*
public
class
ViewModel
{
public
VirtualQueryableCollectionView View {
get
;
set
; }
Controller controller;
public
ViewModel()
{
controller =
new
Controller();
View =
new
VirtualQueryableCollectionView(controller.GetList()) { LoadSize = 10 };
}
}
}
Controller.cs
using
System;
using
System.Linq;
namespace
TelerikVirtualization
{
public
class
Controller
{
public
IQueryable GetList()
{
DataClasses1DataContext context =
new
DataClasses1DataContext();
var result = from x
in
context.MyTables
select
new
MyTableEntity() {
Date = x.Date.GetValueOrDefault(DateTime.Now),
Name = x.Name,
UnitPrice = x.UnitPrice.GetValueOrDefault(0),
id = x.ID,
Discontinued = x.Discontinued,
Children = (from y
in
context.MyChildTables
where y.ParentID == x.ID
select
new
MyChildTableEntity { ID = y.ID, Name = y.Name, ParentID = y.ParentID })
};
return
result;
}
}
public
class
MyTableEntity
{
public
int
id {
get
;
set
; }
public
string
Name {
get
;
set
; }
public
decimal
UnitPrice {
get
;
set
; }
public
DateTime Date {
get
;
set
; }
public
object
Children {
get
;
set
; }
public
bool
? Discontinued {
get
;
set
; }
}
public
class
MyChildTableEntity
{
public
int
ID {
get
;
set
; }
public
string
Name {
get
;
set
; }
public
int
? ParentID {
get
;
set
; }
}
}
Thank you.
24 Answers, 1 is accepted
The correct approach in this scenario would be to set RadGridView's IsBusy property to True and then return it to False in the GridView's DataLoaded event.
public
MainWindow()
{
InitializeComponent();
DataContext =
new
ViewModel();
this
.RadGridView.DataLoaded += RadGridView_DataLoaded;
}
private
void
RadGridView_DataLoaded(
object
sender, EventArgs e)
{
this
.RadGridView.IsBusy =
false
;
}
Please let me know if this answers your question. Don't hesitate to contact us again should any further questions or concerns arise.
Regards,
Dilyan Traykov
Telerik
Hi Dilyan.
If I use that code, the spinner won't show at all.
please try to reproduce my scenario on your side, you have my code
thank you
I did try to reproduce your scenario, but the behavior I get is expected. The reason the BusyIndicator is not shown is that RadGridView loads the items instantaneously. To simulate the loading of items, I've added a 2-second delay. You can see that once the items are actually loaded, the indicator is hidden.
I'm attaching a modified version of your project to my reply. Please let me know if I've missed something important.
Regards,
Dilyan Traykov
Telerik
but if I modify your sample and remove that timer, the list will take some time to load (cos its 1 million rows), but wont show the spinner...
can you try that scenario?
thank you
I've modified my sample project and attached it to my reply. It makes use of the ItemsLoading and ItemsLoaded events of the VirtualQueryableCollectionView and displays the IsBusyIndicator when necessary. Please note that with this approach, the IsBusyIndicator will be shown each time the ItemsLoading is called.
Could you please have a look at the attached project and let me know if this approach would work for you?
I would also like to ask - is there a specific reason you're using a VirtualQueryableCollectionView? If that is not the case, maybe I can offer another solution based on your specific requirements.
Regards,
Dilyan Traykov
Telerik
Yes there is:
I followed your documentations regarding an endless scrolling (virtualization load) method. because your pagination via RadPageControl is broken when we apply the filter on the grid.
the endless scrolling works really fine with the filter and everything
I will give your solution a try and return in a minute
It is WORKING!!!
Thank you once more
There is just one detail that is missing:
the spinner doesn't "spin"
it only shows there, without animation.
what's wrong?
Such behavior would be expected, as both the animation and the data loading are executed on the UI thread. You need to move the time consuming operation on a separate thread. This can be achieved by using a Background Worker. You may also find the How to use WPF Background Worker StackOverflow thread useful.
Hope this helps.
Regards,
Stefan X1
Telerik
Hi Stefan
The logic of the backgroundworker is reasonable to solve this problem. but it won't match with Dilyan Traykov last solution.
because it needs to use the fully initialized View (list) and set the View_ItemsLoading and View_ItemsLoaded events upon it
when I use the BackgroundWorker, it will simply throw me a null exception
I will need a little more time to search for a solution for your scenario, but I will get back to you as soon as possible.
Regards,
Dilyan Traykov
Telerik
Thank you very much Dilyan.
I will be looking forward to hear from you
Thank you for your patience.
Another approach I can suggest is to wrap your RadGridView in a RadBusyIndicator with a DisplayAfter property set to 0​ and then set its (rather than RadGridView's) IsBusy property in the ItemsLoading and ItemsLoaded events:
<
telerik:RadBusyIndicator
Name
=
"busyIndicator"
IsBusy
=
"True"
DisplayAfter
=
"0"
>
<
telerik:RadGridView
Name
=
"RadGridView"
/>
</
telerik:RadBusyIndicator
>
private
void
View_ItemsLoaded(
object
sender, VirtualQueryableCollectionViewItemsLoadedEventArgs e)
{
this
.busyIndicator.IsBusy =
false
;
}
private
void
View_ItemsLoading(
object
sender, VirtualQueryableCollectionViewItemsLoadingEventArgs e)
{
this
.busyIndicator.IsBusy =
true
;
}
Please let me know if you're satisfied with the result from this approach.
Regards,
Dilyan Traykov
Telerik
FLAWLESS!
Thank you very much!
I must retract what I have just said.
The solution (actually both of them) fails when grouping.
But it will still do for now. But please verify that further on...
I might need to come back to this ticket later
In order to group the items correctly, the VirtualQueryableCollectionView needs to load all the items beforehand and the ItemsLoading and ItemsLoaded events do not get fired.
Please let me know if this clarifies things for you.
Regards,
Dilyan Traykov
Telerik
Hey Dilyan,
Yes it does. And it also explains why the performance is not the best when grouping...
So there is no way of using a IsBusy indicator for the case?
I tried handling the Grouping and Grouped events, for no use
If you want to display the BusyIndicator when grouping and expanding the groups, you can use the following event handlers, which seem to be working fine at my end:
public
MainWindow()
{
InitializeComponent();
DataContext =
new
ViewModel();
var view = (
this
.DataContext
as
ViewModel).View;
view.ItemsLoading += View_ItemsLoading;
view.ItemsLoaded += View_ItemsLoaded;
this
.RadGridView.Grouping += RadGridView_Grouping;
this
.RadGridView.Grouped += RadGridView_Grouped;
this
.RadGridView.GroupRowIsExpandedChanging += RadGridView_GroupRowIsExpandedChanging;
this
.RadGridView.GroupRowIsExpandedChanged += RadGridView_GroupRowIsExpandedChanged;
}
private
void
RadGridView_GroupRowIsExpandedChanged(
object
sender, Telerik.Windows.Controls.GridView.GroupRowEventArgs e)
{
this
.busyIndicator.IsBusy =
false
;
}
private
void
RadGridView_GroupRowIsExpandedChanging(
object
sender, Telerik.Windows.Controls.GridView.GroupRowCancelEventArgs e)
{
this
.busyIndicator.IsBusy =
true
;
}
private
void
RadGridView_Grouped(
object
sender, GridViewGroupedEventArgs e)
{
this
.busyIndicator.IsBusy =
false
;
}
private
void
RadGridView_Grouping(
object
sender, GridViewGroupingEventArgs e)
{
this
.busyIndicator.IsBusy =
true
;
}
private
void
View_ItemsLoaded(
object
sender, VirtualQueryableCollectionViewItemsLoadedEventArgs e)
{
this
.busyIndicator.IsBusy =
false
;
}
private
void
View_ItemsLoading(
object
sender, VirtualQueryableCollectionViewItemsLoadingEventArgs e)
{
this
.busyIndicator.IsBusy =
true
;
}
I've attached a modified version of my sample project to demonstrate this. Could you verify that you're using the same approach?
Regards,
Dilyan Traykov
Telerik
Hello Dilyan.
I wish I could give you good news, but I used your sample and I couldn't get it to run.
but as I noticed it approaches a slight different scenario, I decided to change is slightly to run it and get closer to my scenario:
Here is what I changed:
Controller.cs
public IQueryable GetList()
{
var context = new DataClasses1DataContext();
var result = context.MyTables;
return result.AsQueryable();
}
MainWindow.xaml:
<
Window
x:Class
=
"TestRadGridView.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
xmlns:my
=
"clr-namespace:TestRadGridView"
Title
=
"MainWindow"
Height
=
"700"
Width
=
"700"
>
<
Window.Resources
>
<
Style
x:Key
=
"VitorStyle"
TargetType
=
"telerik:RadGridView"
>
<
Setter
Property
=
"AutoGenerateColumns"
Value
=
"False"
></
Setter
>
<
Setter
Property
=
"FilteringMode"
Value
=
"FilterRow"
></
Setter
>
</
Style
>
</
Window.Resources
>
<
Grid
>
<
telerik:RadBusyIndicator
Name
=
"busyIndicator"
IsBusy
=
"True"
DisplayAfter
=
"0"
>
<
telerik:RadGridView
Name
=
"RadGridView"
ItemsSource
=
"{Binding View}"
AutoGenerateColumns
=
"True"
>
</
telerik:RadGridView
>
</
telerik:RadBusyIndicator
>
</
Grid
>
</
Window
>
And I added a Lint to SQL (dbml) file containing only one table (1 million rows on it. each with a random name and some random columns)
This is it. And the grouping won't show the Spinner.
I'm reattaching the modified project. At my end, it successfully displays the BusyIndicator once I group the items. Could you please have a look and let me know how this goes at your end?
Regards,
Dilyan Traykov
Telerik
sorry but your sample doesn't reflect my scenario.
My last post shows how to do so.
- linq to sql
- 1 million rows
I have modified my project accordingly, but everything is still working as expected. Could you please modify the attached project or maybe send over a sample project of your own that demonstrates the behavior you're observing at your end?
Thank you in advance for your cooperation on the matter.
Regards,
Dilyan Traykov
Telerik
Hi raneesras,
As per your request, I've prepared a small sample project demonstrating how to bind the IsBusy property of the control to a property in your viewmodel and use this property to display the indicator while the data is loading.
Please have a look and let me know if you find this example helpful.
Regards,
Dilyan Traykov
Progress Telerik