Design Time Data for Xamarin.Forms

Design Time Data for Xamarin.Forms

In my previous post I showed how to switch between Visual States using the tooling that comes with the BuildIt.Forms library. One of the other features of the tooling is the ability to load mock data that can assist with visualising how a page might look like with certain data. Rather than try to guess at what data your page might require, the tooling simply allows you to define a series of design actions. Each design action will appear within the BuildIt.Forms flyout, allowing you to invoke the action.

Let’s demonstrate this with an example. I’m going to change the layout of my page slightly so that in the DataLoaded state a ListView is displayed that takes up the entire screen. The XAML for the ListView is as follows:

<ListView x_Name=”DataList” IsVisible=”false”>
     <ListView.ItemTemplate>
         <DataTemplate>
             <ViewCell>
                 <Label Text=”{Binding Name}” />
             </ViewCell>
         </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

As I don’t have any actual data at the moment, when I run up the application and click the Load Data button I see the following for the DataLoaded state:

image

This isn’t great as I’ve got no idea what my ListView is going to look like. So let’s fix this by adding a design action. I do this by calling the AddDesignAction method (it’s an extension method which is why I can access it on the MainPage) and providing a name, “Mock Data”, and the action to perform when the design action is run.

public MainPage()
{
     InitializeComponent();


    var groups = VisualStateManager.GetVisualStateGroups(this);

#if DEBUG
     this.AddDesignAction(“Mock Data”,
         () =>
         {
             var data = from i in new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
                        select new { Name = $”Item {i}” };
             DataList.ItemsSource = data;
         });
#endif
}

In this case I’m creating an IEnumerable of an anonymous type that has a property Name, which aligns with the data binding in the ListView XAML shown earlier. I’m assigning this directly to the ItemsSource of the ListView – at this stage I’m just creating the layout of the pages of my application so I might not even have View Models, which is why I’m assigning directly to the ItemSource property in place of data binding it.

Now when I run the application I see:

imageimage

imageimage

The final image shows the list of items being displayed in the ListView – clearly this layout could do with some work!

Visual State Manager Tooling in Xamarin.Forms With BuildIt.States

Visual State Manager Tooling in Xamarin.Forms With BuildIt.States

Back in the days of Silverlight/Windows Phone Microsoft launched a tool called Expression Blend that allowed developers and designer to work in harmony with developers doing their thing (ie write code) in Visual Studio and designers creating the user experience in XAML using Expression Blend. Fast forward a few years and Expression Blend has been rebadged to Blend for Visual Studio and most of the features of Blend have now been migrated to Visual Studio. With the demise of Windows Phone and the lack of developer interest in building for just Windows, Blend is now a tool that most developers have all but forgotten. So, why am I bringing this up now? Well, one of the features I missed from Blend is the ability to have design time data that allows you to build out the entire user interface, with the design time data being replace by real data when the application is run. Whilst there have been some attempts at providing a design time experience for Xamain/Xamarin.Forms, the reality is that it comes no where close to what Blend was able to do in its heyday.

If we look at other platforms, such as React Native, there has been a shift away from design time experience, across to an interactive runtime experience. By this I mean the ability to adjust layout and logic of the application whilst it’s running, which relies on the platform being able to hot-reload both layout and logic of the application. There are some third party tools for Xamarin.Forms that partially enable this functionality.

One of the challenges I found when working with Visual States is that you often need to get the application to a certain point, or follow a particular sequence of steps in order to get a specific Visual State to appear. Take the example I provided in my previous post on page states where I provided DataLoaded and DataFailedToLoad states – in the example the appearance of these states was completely random, so you might have to click the button a couple of times in order to get the state to appear. Luckily, the BuildIt.Forms library has a slightly-hidden feature that allows you to manually switch between states. I say it’s slightly-hidden because if you connect your Visual States to a StateManager in your ViewModels (shown in either this post or this post) you’ll see this feature automatically. In the example I covered in my previous post I needed to add the following line to the end of the MainPage constructor:

public MainPage()
{
     InitializeComponent();
    var groups = VisualStateManager.GetVisualStateGroups(this);
}

Now, when I run the application I see a small dot appear in the bottom left of the screen.

image

Clicking on the dot reveals a flyout that allows you to switch states:

App14UWP20190317125937

Note that this is only shown when the Visual Studio debugger is attached so will not impact the way your application works in release mode.

Page State with the Visual States Manager for Xamarin.Forms

Page State with the Visual States Manager for Xamarin.Forms

One of the current limitations of the Xamarin.Forms implementation of the Visual State Manager (VSM) is that it only works for setting properties on an individual control. Whilst this is great for control state management (think button states like disabled, pressed etc), its incredibly limiting and makes it unsuitable for some typical visual state scenarios. The one that often comes up in a mobile application is for pages that load data. In this scenario you typically have a least three states: Loading, DataLoaded, DataFailedToLoad. In some cases you might even extend this to have states such as Refreshing or LoadingMoreData. For these states you probably want to show/hide different elements on the screen, which is why the current Xamarin.Forms implementation of the VSM isn’t a great option.

Luckily there’s an alternative, which is the Visual State Manager that’s part of the BuildIt.Forms library. Here’s a quick example of it in action:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<ContentPage
             
             
              x_Class=”App14.MainPage”>
     <vsm:VisualStateManager.VisualStateGroups>
         <vsm:VisualStateGroups>
             <vsm:VisualStateGroup Name=”LoadingStates”>
                 <vsm:VisualState Name=”Loading”>
                     <vsm:VisualState.Setters>
                         <vsm:Setter Value=”True” Element=”{x:Reference LoadingLabel}” Property=”IsVisible” />
                     </vsm:VisualState.Setters>
                 </vsm:VisualState>
                 <vsm:VisualState Name=”DataLoaded”>
                     <vsm:VisualState.Setters>
                         <vsm:Setter Value=”True” Element=”{x:Reference LoadedLabel}” Property=”IsVisible” />
                     </vsm:VisualState.Setters>
                 </vsm:VisualState>
                 <vsm:VisualState Name=”DataFailedToLoad”>
                     <vsm:VisualState.Setters>
                         <vsm:Setter Value=”True” Element=”{x:Reference FailedLabel}” Property=”IsVisible” />
                     </vsm:VisualState.Setters>
                 </vsm:VisualState>
             </vsm:VisualStateGroup>
         </vsm:VisualStateGroups>
     </vsm:VisualStateManager.VisualStateGroups>

     <StackLayout VerticalOptions=”Center”>
         <Label Text=”Loading…” x_Name=”LoadingLabel” HorizontalOptions=”Center”  IsVisible=”False” />
         <Label Text=”Success: Data Loaded!!” x_Name=”LoadedLabel” HorizontalOptions=”Center” IsVisible=”False” />
         <Label Text=”Failure :-(” x_Name=”FailedLabel” HorizontalOptions=”Center” IsVisible=”False” />
         <Button Text=”Load Data” Clicked=”LoadClicked” />
     </StackLayout>
</ContentPage>

In this case we’ve defined three Visual States that correspond to showing the LoadingLabel, LoadedLabel and FailedLabel respectively. The code behind for the LoadClicked method illustrates how easily you can switch between the states:

private readonly Random rnd = new Random();


private async void LoadClicked(object sender, EventArgs e)
{
     var success = rnd.Next(0, 1000) % 2 == 0;
     await VisualStateManager.GoToState(this, “Loading”);
     await Task.Delay(2000);
     await VisualStateManager.GoToState(this, success ? “DataLoaded” : “DataFailedToLoad”);
}

Ok, so one last thing we can add in is a bit of animation to make the transition between states a little smoother. Let’s fade our labels in and out:

<vsm:VisualState Name=”Loading”>
     <vsm:VisualState.ArrivingAnimations>
         <animations:AnimationGroup>
             <animations:AnimationGroup.PostAnimations>
                 <animations:FadeAnimation Opacity=”1″
                                           Duration=”500″
                                           Element=”{x:Reference LoadingLabel}” />
             </animations:AnimationGroup.PostAnimations>
         </animations:AnimationGroup>
     </vsm:VisualState.ArrivingAnimations>
     <vsm:VisualState.LeavingAnimations>
         <animations:AnimationGroup>
             <animations:AnimationGroup.PreAnimations>
                 <animations:FadeAnimation Opacity=”0″
                                           Duration=”500″
                                           Element=”{x:Reference LoadingLabel}” />
             </animations:AnimationGroup.PreAnimations>
         </animations:AnimationGroup>
     </vsm:VisualState.LeavingAnimations>

     <vsm:VisualState.Setters>
         <vsm:Setter Value=”True” Element=”{x:Reference LoadingLabel}” Property=”IsVisible” />
     </vsm:VisualState.Setters>
</vsm:VisualState>

The XAML adds a fade in after the state transition has occurred (Post animation) when transitioning to (Arriving at) the the Loading state, and a fade out before the state transition has occurred (Pre animation) when transitioning from (Leaving) the Loading state. As you can see the XAML gets fairly verbose but it’s structured this way to allow for complex combinations and sequences of animations:

<animations:AnimationGroup.PostAnimations>
     <animations:SequenceAnimation>
         <animations:ParallelAnimation>
             <animations:FadeAnimation Opacity=”1″ Duration=”500″ Element=”{x:Reference LoadingLabel}” />
             <animations:ScaleAnimation Scale=”5″ Duration=”500″ Element=”{x:Reference LoadingLabel}” />
             <animations:SequenceAnimation>
                 <animations:RotateAnimation Rotation=”10″ Duration=”250″ Target=”LoadingLabel” />
                 <animations:RotateAnimation Rotation=”0″ Duration=”250″ Target=”LoadingLabel” />
                 <animations:RotateAnimation Rotation=”-10″ Duration=”250″ Target=”LoadingLabel” />
                 <animations:RotateAnimation Rotation=”0″ Duration=”250″ Target=”LoadingLabel” />
             </animations:SequenceAnimation>
         </animations:ParallelAnimation>
         <animations:ScaleAnimation Scale=”1″ Duration=”500″ Element=”{x:Reference LoadingLabel}” />
     </animations:SequenceAnimation>
</animations:AnimationGroup.PostAnimations>

And let’s see this in action:

App14UWP20190317022241

Hopefully you can see from this short post how you can leverage the BuildIt.Forms Visual State Manager to do complex page state management as well as animations. We’ve just released a new beta package compatible with the latest Xamarin.Forms v3.6 and would love feedback (https://www.nuget.org/packages/BuildIt.Forms/2.0.0.27-beta).