Using BuildIt.Lifecycle with Xamarin Forms

Using BuildIt.Lifecycle with Xamarin Forms

Leaving the Universal Windows Platform behind for a little bit I wanted to show that the BuildIt.Lifecycle framework can be used to drive a Xamarin Forms (XForms) application.

The first step is to create a Xamarin Forms project. In this case I’ll select the Portable option.

image

This will actually create four projects, one which is contains the actually application logic, including the XAML markup for the pages, and then three platform specific projects for iOS, Droid and Windows Phone. The platform specific projects are where any code required for device integration or custom UX goes for each platform.

After creating the projects, the first thing to do is to upgrade the Xamarin.Forms NuGet reference to the latest version (v2.0.1.6495 at time of writing).

The next thing to do is to add references to the BuildIt.Lifecycle NuGet packages including the Xamarin Forms specific package (https://www.nuget.org/packages/BuildIt.Lifecycle.XForms ). I had a few issues here because I initially had the dependency setting in the NuGet manager set to Lowest and it refused to install one of the dependencies (NuGet still isn’t clever enough some times to resolve everything properly). Switching this to Highest, which I think should be the default, fixed this issue.

Of course, the core XForms project needs a reference to the SimpleStates.Core library which contains all my application, region and view model classes. At this point I realised I hadn’t set the PCL profile correctly on the project. Updating this turned out to be a bit of a mission as Visual Studio insisted the project had to be switched to NuGet v3, which you can’t do with any packages installed (according to the error message). So I had to uninstall all the NuGet packages (in the correct order) one at a time, and then update the targets as per the Change Targets dialog for the project.

image

Now that the projects have all the references I need, it’s time to wire up the application. To do this I need to initialise the BuildIt.Lifecycle application, and I need a XForms page that maps to each of the pages (ie my states) in the application. Creating the pages is the easiest thing as they all come straight from the Forms Xaml Page template (no changing of base page required!!).

image

The image shows me creating the MainPage but I also added a SettingsPage, AboutPage and LandingPage into the Pages folder in my XForms PCL project.

Hooking up the BuildIt.Lifecycle framework was also relatively easy. In the App.cs, I simply replace the in-code page that’s created when you create the new project with the following:

public class App : Application
{
    public App()
    {
        LifecycleHelper.RegisterView<MainPage>().ForState(AppStates.Home);
        LifecycleHelper.RegisterView<SettingsPage>().ForState(AppStates.Settings);
        LifecycleHelper.RegisterView<AboutPage>().ForState(AppStates.About);

        LifecycleHelper.RegisterView<LandingPage>().ForState(AdditionalStates.Landing);

        MainPage = new NavigationPage();
        StartApplication();
    }

    private async void StartApplication()
    {
        var core = new SimpleStatesApplication();
        var wm = new WindowManager(MainPage as NavigationPage, core);
        await core.Startup(builder =>
        {
            builder.RegisterType<FormsDataService>().As<IDataService>();
        });
    }
}

This also requires an implementation of IDataService which I called FormsDataService and returns slightly different Contacts than the UWP version did, just to prove the point.

public class FormsDataService : IDataService
{
    public async Task<IEnumerable<string>> LoadContacts()
    {
        return new[] { “XF: Joe”, “XF: Bob”, “XF: Frank” };
    }
}

My application will now run and display the MainPage but won’t show any content. To fix this I simply needed to go through each of the pages, translate the UWP XAML into XForms and then wire up any event handlers in the code-behind (which route through to the ViewModel anyhow). The XAML and code behind (where required) for the four pages is at the end of this post…. You’ll note that I cheated on the About page just to get something displaying (I’ll come back to that to implement visual states etc) and that neither the About, nor the Landing page currently have any code behind.

That’s it – I can run the application and my page transitions work without me having to do anything. This is very much in early stages as you’ll see that the back navigation isn’t working properly (it’s actually a forward navigation at the moment) and the navigation back button exists even on the first page of the application, which isn’t correct. In coming posts we’ll clear these issues up.

 

<?xml version=”1.0″ encoding=”utf-8″ ?>
<ContentPage http://xamarin.com/schemas/2014/forms"”>http://xamarin.com/schemas/2014/forms”
             http://schemas.microsoft.com/winfx/2009/xaml"”>http://schemas.microsoft.com/winfx/2009/xaml”
             x_Class=”SimpleStates.XForms.Pages.MainPage”>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height=”Auto”/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <StackLayout >
      <Label Text=”Main Page”
                  
                 FontSize=”40″ />
      <Button Clicked=”SettingsClick”>Settings</Button>
      <Button Clicked=”AboutClick”>About</Button>
      <Button Clicked=”AnotherWindowClick”>Another Window</Button>
    </StackLayout>
    <ListView Grid.Row=”1″ ItemsSource=”{Binding Contacts}”></ListView>
  </Grid>
</ContentPage>

public partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();
    }
    private MainViewModel ViewModel => BindingContext as MainViewModel;
    private void SettingsClick(object sender, EventArgs e)
    {
        ViewModel.DisplaySettings();
    }

    private void AboutClick(object sender, EventArgs e)
    {
        ViewModel.DisplayAbout();
    }
    private void AnotherWindowClick(object sender, EventArgs e)
    {
        ViewModel.OpenAnotherWindow();
    }
}

<?xml version=”1.0″ encoding=”utf-8″ ?>
<ContentPage http://xamarin.com/schemas/2014/forms"”>http://xamarin.com/schemas/2014/forms”
             http://schemas.microsoft.com/winfx/2009/xaml"”>http://schemas.microsoft.com/winfx/2009/xaml”
             x_Class=”SimpleStates.XForms.Pages.SettingsPage”>

  <StackLayout VerticalOptions=”Center” HorizontalOptions=”Center”>
    <Label Text=”Settings Page”
               FontSize=”40″ />
    <Label Text=”{Binding SettingsTitle}”
               FontSize=”40″ />
    <Button Clicked=”GoBackClick”>Go Back</Button>
  </StackLayout>
</ContentPage>

public partial class SettingsPage
{
    public SettingsPage()
    {
        InitializeComponent();
    }
    private void GoBackClick(object sender, EventArgs e)
    {
        (BindingContext as SettingsViewModel)?.CompleteSettings();
    }
}

<?xml version=”1.0″ encoding=”utf-8″ ?>
<ContentPage http://xamarin.com/schemas/2014/forms"”>http://xamarin.com/schemas/2014/forms”
             http://schemas.microsoft.com/winfx/2009/xaml"”>http://schemas.microsoft.com/winfx/2009/xaml”
             x_Class=”SimpleStates.XForms.Pages.AboutPage”>
  <StackLayout VerticalOptions=”Center” HorizontalOptions=”Center” >
    <Label  Text=”About Page”
                   FontSize=”40″ />
    <Label  Text=”{Binding AboutTitle}”
             FontSize=”40″ />
    <Label  Text=”{Binding Data}”
             FontSize=”40″ />
  </StackLayout>
</ContentPage>

<?xml version=”1.0″ encoding=”utf-8″ ?>
<ContentPage http://xamarin.com/schemas/2014/forms"”>http://xamarin.com/schemas/2014/forms”
             http://schemas.microsoft.com/winfx/2009/xaml"”>http://schemas.microsoft.com/winfx/2009/xaml”
             x_Class=”SimpleStates.XForms.Pages.LandingPage”>
  <Label Text=”Landing” VerticalOptions=”Center” HorizontalOptions=”Center” FontSize=”40″ />
</ContentPage>

Leave a Reply

Your email address will not be published. Required fields are marked *