Borjan Stojcev
Borjan Stojcev

Reputation: 76

How to create a page with two layouts in xamarin forms

I am working on a mobile application with xamarin forms. I've created a page which first will try to make an API request and then display some data from the API's result. In case when the API request will fail I want to display another layout with a retry button. Is this possible and if it is, how can I do it?

Upvotes: 0

Views: 193

Answers (1)

Roubachof
Roubachof

Reputation: 3401

I created a Xamarin.Forms component for async loading and errors handling. It's a container of any view. If the Task throws an exception it displays a specified Image as well as a retry button. Have a look:

<customViews:TaskLoaderView  
    Grid.Row="2"
    Style="{StaticResource SillyTaskLoader}"
    ViewModelLoader="{Binding SillyPeopleLoader}">

    <Grid ColumnSpacing="0" RowSpacing="0">

        <Grid.RowDefinitions>
            <RowDefinition 
                x:Name="SillyOfTheDayHeader" 
                Height="{StaticResource HeaderHeight}" />
            <RowDefinition Height="144" />
            <RowDefinition 
                x:Name="ListViewHeader" 
                Height="{StaticResource HeaderHeight}" />
            <!--  ItemHeight + VerticalMargin + VerticalPadding  -->
            <RowDefinition Height="176" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <!--  ROW 0: Silly Of The Day Header  -->
        <Label 
            Grid.Row="0"
            Style="{StaticResource TextHeader}"
            Text="{loc:Translate SillyPeople_SillyOfTheDay}" />

        <!-- etc -->

    </Grid>

</customViews:TaskLoaderView>  

And the view model:

public class SillyPeopleVm : ANavigableViewModel  
{
    private readonly ISillyDudeService _sillyDudeService;

    public SillyPeopleVm(
        INavigationService navigationService, 
        ISillyDudeService sillyDudeService, 
        ErrorEmulator errorEmulator)
        : base(navigationService)
    {
        _sillyDudeService = sillyDudeService;
        InitCommands();

        SillyPeopleLoader = new 
            ViewModelLoader<ObservableCollection<SillyDudeVmo>>( 
                ApplicationExceptions.ToString, 
                SillyResources.Empty_Screen);
    }

    public ErrorEmulatorVm ErrorEmulator { get; }

    public SillyDudeVmo SillyOfTheDay { get; private set; }

    public ViewModelLoader<ObservableCollection<SillyDudeVmo>> 
        SillyPeopleLoader { get; }

    public override void Load(object parameter)
    {
        SillyPeopleLoader.Load(LoadSillyPeopleAsync);
    }

    private async Task<ObservableCollection<SillyDudeVmo>> LoadSillyPeopleAsync()
    {
        SillyOfTheDay = new SillyDudeVmo(
            await _sillyDudeService.GetRandomSilly(), GoToSillyDudeCommand);
        RaisePropertyChanged(nameof(SillyOfTheDay));

        return new ObservableCollection<SillyDudeVmo>(
            (await _sillyDudeService.GetSillyPeople())
                .Select(dude => 
                    new SillyDudeVmo(dude, GoToSillyDudeCommand)));
    }
}

https://www.sharpnado.com/taskloaderview-async-init-made-easy/

Upvotes: 2

Related Questions