We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Async OnDemandLoading

Hi,

I'm having trouble using the OnDemandLoading feature of SfDataPager with asynchronous event handlers.

Based on the OnDemandPaging example that comes with the sample browser, I changed

        //OnDemandPaging class
        private void OnDemandPageLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
        {
                sfDataPager.LoadDynamicItems(args.StartIndex, source.Skip(args.StartIndex).Take(args.PageSize));
        }

to

        private async void OnDemandPageLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
        {
                await Task.Delay(1);
                sfDataPager.LoadDynamicItems(args.StartIndex, source.Skip(args.StartIndex).Take(args.PageSize));
        }

The problem is, that the  newly loaded data isn't displayed. However, data is displayed when a page is rendered a second time, e.g.
  1. Navigate to page n (loads the data, but doesn't display it)
  2. Navigate to page n-1
  3. Navigate to page n again, this time data is rendered
Do you have some advice/best practice w.r.t. on damand data binding with async?

5 Replies

JG Jai Ganesh S Syncfusion Team March 10, 2016 01:12 PM UTC

Hi Jasper,


We have analyzed your query. In your query, the LoadDynamicItems is invoked only after await is completed. So you have to call the PagedSource.Refresh () method after invoking the LoadDynamicItems method like the below code example,


Code Example:


private async void OnDemandPageLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)

 {

       await Task.Delay(1);

       sfDataPager.LoadDynamicItems(args.StartIndex, source.Skip(args.StartIndex).Take(args.PageSize));

        sfDataPager.PagedSource.Refresh();

 }



We already have a kb to load the pages in OnDemand using async and await and the kb kink as below,


Kb Link:

https://www.syncfusion.com/kb/6133/how-to-load-pages-in-ondemand-using-async-await


Regards,

Jai Ganesh S



JA Jasper March 10, 2016 05:41 PM UTC

Hi Jai,

thanks a lot! sfDataPager.PagedSource.Refresh() works beautiful.

Regarding the KB: While the code looks like async it actually isn't (at least the UWP version, haven't checked other platforms). In GetEmployeesDetailsListAync(int startindex, int pagesize) a call to Task.Delay(2000).Wait() is made. Task.Wait() however is (according to my understanding) synchronous, hence blocking the UI thread. Therefore the sample code works w/o calling sfDataPager.PagedSource.Refresh().

Now I'm facing a similar problem with the KB sample for async loading of detail views in hierarchical grids (https://www.syncfusion.com/kb/2394/how-to-load-detailsview-itemssource-asynchronously). The sample code is actually running synchronously, blocking the UI thread. 

I would be grateful if you could tell me what I have to do to update/refresh a detail grid (making it show the data) after adding the items source it asynchronously. I couldn't even manage to get a reference to the opened detail grid.


JG Jai Ganesh S Syncfusion Team March 11, 2016 09:58 AM UTC

Hi Jasper,


We are adding the ItemsSource as asynchronously in detailsviewdatagrid as like in the following kb https://www.syncfusion.com/kb/2394/how-to-load-detailsview-itemssource-asynchronously) and the details view items are loaded as expected.  Could you please modify the below sample to reproduce the reported issue. This would be more helpful for us to analyze further.


Sample:

http://www.syncfusion.com/downloads/support/directtrac/153477/ze/UWP2138393894-618551728


Regards,

Jai Ganesh S



JA Jasper March 11, 2016 10:59 AM UTC

Hi Jai,

the problem with the example is, that it calls WaitHandle.WaitOne(Int 32). WaitOne() blocks the current thread (current thread is the UI thread, for details on WaitOne see https://msdn.microsoft.com/en-us/library/cc189907(v=vs.110).aspx) which makes using async/await pretty much pointless, it's actually equivalent to not using async/await at all. 
You can actually see that the sample code blocks the UI thread. Try to resize/move the application window after expanding a detail grid and before the detail grid is shown (you may want to pass a reasonably high number to sleep(Int32) for demonstration purposes). Making any modifications to the UI won't work during that timeframe because the UI thread is blocked.
If you don't block the thread (e.g. using await Task.Delay(Int 32)) the sample does not work, the details data grid is not populated/visible.

Without any blocking code GetItems() could look like this:

private async Task<List<dynamic>> GetItems(){
    var list = new List<dynamic>();
    await Task.Delay(2000);

    list.Add(CreateDynamicObj("David", 1001, "Asst.Manager", 118));
    list.Add(CreateDynamicObj("Alex", 1002, "Senior Developer", 123));
    list.Add(CreateDynamicObj("Christopher", 1003, "Senior Developer", 121));
    return list;
}

This is truly async, it doesn't block the thread. However, with this code the detail grid isn't populated/visible. I would need a way to update/refresh the detail grid when GetItems() actually returns, like I can refresh the data pager once I have received the data.


JS Jayapradha S Syncfusion Team March 14, 2016 01:26 PM UTC

Hi Jasper,

 

We analyzed your query.  In that KB Sample, We have removed the Sleep method and used Task.Delay. It is not possible to provide complete list to SfDataGrid asynchronously, But you can add items to SfDataGrid details view asynchronously without blocking current thread for getting items from service.

 

Code Example:

 

private void SfGrid_DetailsViewExpanding(object sender,

            Syncfusion.UI.Xaml.Grid.GridDetailsViewExpandingEventArgs e)

        {

            e.DetailsViewItemsSource.Clear();

            var list = new ObservableCollection<dynamic>();

            e.DetailsViewItemsSource.Add("Persons", list);

            var underlyingList = GetItems(list);

        }

private async Task<ObservableCollection<dynamic>> GetItems(ObservableCollection<dynamic> dynamicList)

        {

            await Task.Delay(2000);

            dynamicList.Add(CreateDynamicObj("David", 1001, "Asst.Manager", 118));

            dynamicList.Add(CreateDynamicObj("Alex", 1002, "Senior Developer", 123));

            dynamicList.Add(CreateDynamicObj("Christopher", 1003, "Senior Developer", 121));

            dynamicList.Add(CreateDynamicObj("Mary", 1004, "Accountant", 120));

            dynamicList.Add(CreateDynamicObj("Angeline", 1005, "Asst.Manager", 105));

            dynamicList.Add(CreateDynamicObj("Andrew", 1006, "Manager", 103));

            dynamicList.Add(CreateDynamicObj("Michael", 1007, "Senior Developer", 124));

 

            return dynamicList;

        }

 

Please refer the modified sample from the below location,

 Sample Link: 

Regarding query: . I would need a way to update/refresh the detail grid when GetItems() actually returns, like I can refresh the data pager once I have received the data.

In the GetItems method, you can add items once you receive data from service.

 

Regards,
Jayapradha


Attachment: UWP_b14b487d.zip

Loader.
Up arrow icon