This is a migrated thread and some comments may be shown as answers.

Busy animation won't display when setting IsBusy = false

7 Answers 675 Views
BusyIndicator
This is a migrated thread and some comments may be shown as answers.
Bill
Top achievements
Rank 1
Bill asked on 04 Dec 2017, 12:30 PM

I am having trouble displaying the BusyIndicator in my project. Here's my XAML:

<?xml version="1.0" encoding="UTF-8"?>
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:telerikListView="clr-namespace:Telerik.XamarinForms.DataControls.ListView;assembly=Telerik.XamarinForms.DataControls"
             xmlns:telerikDataControls="clr-namespace:Telerik.XamarinForms.DataControls;assembly=Telerik.XamarinForms.DataControls"
             xmlns:iconize="clr-namespace:FormsPlugin.Iconize;assembly=FormsPlugin.Iconize"
             xmlns:upTimeMobile="clr-namespace:UpTimeMobile;assembly=UpTimeMobile.Android"
             xmlns:lc="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
             xmlns:lb="clr-namespace:XLabs.Forms.Behaviors;assembly=XLabs.Forms"
             xmlns:lcon="clr-namespace:XLabs.Forms.Converter;assembly=XLabs.Forms"
             xmlns:lp="clr-namespace:XLabs.Forms.Pages;assembly=XLabs.Forms"
             xmlns:telerikBusyIndicator="clr-namespace:Telerik.XamarinForms.Primitives;assembly=Telerik.XamarinForms.Primitives"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             x:Class="MyApp.Views.Details">
    <telerikBusyIndicator:RadBusyIndicator x:Name="BusyIndicator"
                                           AnimationType="Animation6"
                                           AnimationContentColor="DodgerBlue"
                                           AnimationContentHeightRequest="100"
                                           AnimationContentWidthRequest="100"
                                           IsBusy="True">
        <telerikBusyIndicator:RadBusyIndicator.Content>
         
            <!-- Radlist goes here... -->
             
        </telerikBusyIndicator:RadBusyIndicator.Content>
    </telerikBusyIndicator:RadBusyIndicator>
</ContentPage>

 

This works, and the busy animation appears on the screen. However, if I try to set the indicator to false, the busy indicator doesn't appear at all when the content page is loading. Here's my code:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Details : ContentPage
{
    public Details(Guid Id, string name)
    {
        InitializeComponent();
         
        BusyIndicator.IsBusy = true;
        DoLoad();
        BusyIndicator.IsBusy = false;
    }
     
    private void DoLoad()
    {
        // do data load here...
        ListViewDetails.ItemsSource = results;
    }
}

 

I also tried using async like this (but still doesn't work):

private async void DoLoad()
{
    await Task.Run(() =>
    {
        // do data load here...
        ListViewDetails.ItemsSource = results;
    });
}

 

My Android project min version is 6.0 (23), target is 6.0 (23), compiled using 8.0. I'm using Telerik UI for Xamarin R3 2017 and I also have SkiaSharp.Views.Forms 1.59.2 installed.

7 Answers, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 04 Dec 2017, 03:48 PM
Hi Bill,

The page constructor isn't an appropriate place to handling data-loading methods. Instead, use OnAppearing (which you can also mark async, this is not possible for constructors).

For example:
protected override async void OnAppearing()
{
    base.OnAppearing();
 
    BusyIndicator.IsBusy = true;
 
    var result = await LoadDataAsync();
 
    ListViewDetails = result;
 
    BusyIndicator.IsBusy = true;
}


Even better, use a try-catch and hide the BusyIndicator in the finally clause:

protected override async void OnAppearing()
{
    base.OnAppearing();
 
    try
    {
        BusyIndicator.IsBusy = true;
 
        var result = await LoadDataAsync();
 
        ListViewDetails = result;
    }
    catch (Exception e)
    {
        Debug.WriteLine(e);
    }
    finally
    {
        BusyIndicator.IsBusy = true;
    }
}


If this doesn't work for you, we'll need to investigate further. You can open a support ticket here and attach your code files so that we can replicate the problem for direct debugging.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Lance | Manager Technical Support
Telerik team
answered on 04 Dec 2017, 04:56 PM
Hello Bill,

Small correction in my last reply's code snippets; in the finally clause I left the IsBusy = true, that should be IsBusy=False. 

Let me share the full code I used to test your report, this way you can see it in action outside of your application.


ViewModel (with async Task for loading data):

public class ViewModel
{
    public ViewModel()
    {
    }
 
    public ObservableCollection<BookItemViewModel> Source { get; set; } = new ObservableCollection<BookItemViewModel>();
 
    public async Task LoadDataAsync()
    {
        var result = await GetItemsAsync();
 
        foreach (var item in result)
        {
            Source.Add(item);
        }
    }
 
    private Task<ObservableCollection<BookItemViewModel>> GetItemsAsync()
    {
        return Task.Run(async () =>
        {
            await Task.Delay(TimeSpan.FromSeconds(3));
 
            return new ObservableCollection<BookItemViewModel>
            {
                new BookItemViewModel {Title = "The Fault in Our Stars ", Author = "John Green", IsInStock = true},
                new BookItemViewModel {Title = "Divergent", Author = "Veronica Roth"},
                new BookItemViewModel {Title = "Gone Girl", Author = "Gillian Flynn", IsInStock = true},
                new BookItemViewModel {Title = "Clockwork Angel", Author = "Cassandra Clare"},
                new BookItemViewModel {Title = "The Martian", Author = "Andy Weir"},
                new BookItemViewModel {Title = "Ready Player One", Author = "Ernest Cline"},
                new BookItemViewModel {Title = "The Lost Hero", Author = "Rick Riordan", IsInStock = true},
                new BookItemViewModel {Title = "All the Light We Cannot See", Author = "Anthony Doerr"},
                new BookItemViewModel {Title = "Cinder", Author = "Marissa Meyer"},
                new BookItemViewModel {Title = "Me Before You", Author = "Jojo Moyes"},
                new BookItemViewModel {Title = "The Night Circus", Author = "Erin Morgenstern"},
            };
 
        });
    }
}


XAML

<ContentPage ... >
 
    <ContentPage.BindingContext>
        <viewModels:ViewModel x:Name="ViewModel"/>
    </ContentPage.BindingContext>
 
    <primitives:RadBusyIndicator x:Name="BusyIndicator"
                                 AnimationType="Animation6"
                                 AnimationContentColor="DodgerBlue"
                                 AnimationContentHeightRequest="100"
                                 AnimationContentWidthRequest="100"
                                 IsBusy="True">
        <primitives:RadBusyIndicator.Content>
 
            <dataControls:RadListView ItemsSource="{Binding Source=}">
                <dataControls:RadListView.ItemTemplate>
                    <DataTemplate>
                        <listView:ListViewTextCell Text="{Binding Title}" Detail="{Binding Author}" />
                    </DataTemplate>
                </dataControls:RadListView.ItemTemplate>
            </dataControls:RadListView>
        </primitives:RadBusyIndicator.Content>
    </primitives:RadBusyIndicator>
</ContentPage>


CODE-BEHIND

[assembly:XamlCompilation(XamlCompilationOptions.Compile)]
namespace Demo.Portable
{
    public partial class MyPage : ContentPage
    {
        public MyPage()
        {
            InitializeComponent();
        }
 
        protected override async void OnAppearing()
        {
            base.OnAppearing();
 
            try
            {
                BusyIndicator.IsBusy = true;
 
                await ViewModel.LoadDataAsync();
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
            finally
            {
                BusyIndicator.IsBusy = false;
            }
        }
    }
}


DATA MODEL

public class BookItemViewModel : NotifyPropertyChangedBase
{
    private string title;
    private string author;
    private bool isInStock;
 
    public string Title
    {
        get => title;
        set
        {
            title = value;
            OnPropertyChanged();
        }
    }
 
    public string Author
    {
        get => author;
        set
        {
            author = value;
            OnPropertyChanged();
        }
    }
 
    public bool IsInStock
    {
        get => isInStock;
        set
        {
            isInStock = value;
            OnPropertyChanged();
        }
    }
}


That code will take 3 seconds to simulate loading data, during which time the RadBusyindicator appears. When the async task is complete, the finally clause is hit and the RadBusyIndicator hides.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Bill
Top achievements
Rank 1
answered on 05 Dec 2017, 10:06 AM
Thanks, that seems to work. Is there a way to make the animation fade-in when it starts, and fade-out when it ends?
0
Bill
Top achievements
Rank 1
answered on 05 Dec 2017, 03:09 PM
Also, is there maybe a better method to place the async Task? Currently, the busy animation will freeze for maybe half a second before the page is actually displayed. It seems like the page isn't ready to be fully rendered at the point the busy animation stops.
0
Lance | Manager Technical Support
Telerik team
answered on 05 Dec 2017, 04:43 PM
Hi Bill,

I'm not seeing the delay, are there other synchronous methods running that would block the UIThread? The async task would not cause a UI thread freeze.

In any case, you could try the NativeControlLoaded event for controls that have native renderers.  For example, the RadListView:

<telerikDataControls:RadListView NativeControlLoaded="MyListView_OnNativeControlLoaded">

private async void MyListView_OnNativeControlLoaded(object sender, EventArgs e)
{
    try
    {
        BusyIndicator.IsBusy = true;
 
        await ViewModel.LoadDataAsync();
    }
    catch (Exception e)
    {
        Debug.WriteLine(e);
    }
    finally
    {
        BusyIndicator.IsBusy = false;
    }
}


Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Bill
Top achievements
Rank 1
answered on 08 Dec 2017, 04:02 PM
Thanks for the info. What about my question about fading-in/fading-out of the animation? Any ideas for the simplest way to accomplish that?
0
Lance | Manager Technical Support
Telerik team
answered on 08 Dec 2017, 07:13 PM
Hello Bill,

For this, you'll want to create a custom animation. See this article for a custom animation example that fades a Label control in an in and out. The key takeaway is that the animation targets the Opacity property of the content, you can do the same for your custom animation.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
BusyIndicator
Asked by
Bill
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
Bill
Top achievements
Rank 1
Share this question
or