Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Shell in v4 of Xamarin.Forms and Visual Studio 2019

Back in late 2018 I did a post on getting started with Shell where I did a “File-New-Project” with Xamarin.Forms Shell. In this post I’m going to do a quick update to that post looking at creating a new Shell application with Visual Studio 2019, and then upgrading to the preview of Xamarin.Forms Shell v4.

As all great projects start, let’s get going with the Create a new project dialog. Search for Xamarin and select the Mobile App (Xamarin.Forms) template.

image

Give some basic project information

image

Select Shell as the application template.

Note: The Windows (UWP) option has come back (removed in the initial release of Visual Studio 2019) when creating Xamarin.Forms applications. However, since Shell isn’t supported by UWP at the moment, the Windows (UWP) option is currently disabled.

image

And there you have it a new Xamarin.Forms application that you can build and run, that leverages Shell.

image

And looks a little like this with bottom tabs and an ADD button in the navigation bar.

image

But let’s see what v4 is going to give us. Select “Include prerelease” and update to the latest packages.

image


Xamarin.Forms Shell v4

One addition that is more of a cosmetic improvement is the naming of ShellItem and ShellSection – I think the initial intent of these were that they should be somewhat abstracted for the actual UI implementation. However, as Shell has matured, the reality is that ShellItem maps to an item that appears in the flyout and an ShellSection maps to a tab…..

Wow, hold on, what are these things ShellItem, ShellSection and ShellContent? If you haven’t been following what the Xamarin.Forms team have been working on then Shell might come as a bit of a surprise. However, as nearly every app developer will admit, one of the most painfully tedious parts of building an application is create and linking all the pages of the application so that the user can navigate between them. The cognitive load of how to do master-details or tabs even in Xamarin.Forms makes it hard for developers to get started. What Shell aims to achieve is to provide a declarative way for you to define how your application is structured.

Essentially Shell represents a hierarchy of navigation elements:

- Shell – this is represents the application as a whole

- ShellItem – these are the first level pages of the application. Currently if there are multiple ShellItems defined, they’ll automatically appear in a Flyout.

- ShellSection – a page can be broken into sections which essentially map to bottom tabs. If a ShellItem only has one ShellSection, no tabs will show.

- ShellContent – this is the actual page content that will be displayed within the bottom tabs. If a ShellSection has multiple ShellContent, tabs will appear at the top of the tab giving you a tab-sandwich display.

In v4, to make it easier for developers to clearly see what was going on, additional classes, FlyoutItem and Tab were added that sub-class ShellItem and ShellSection respectively. The following example layouts use the new element names – if you’re still on v3.6 of Xamarin.Forms you will need to stick with ShellItem and ShellSection.

Some examples:

Single Page Application

image

Notes:

- For a single ShellContent there’s no need to include a Tab element, simply nest it directly under the FlyoutItem.

- The FlyoutBehavior attribute can be used to hide/show the flyout on different pages in the application, or (as in this case) across the whole application. Use Shell.FlyoutBehavior on individual FlyoutItem elements to hide the flyout on those pages.

<Shell ... FlyoutBehavior="Disabled">
     <FlyoutItem ... >
         <ShellContent ... />
     </FlyoutItem>
</Shell>

Two Page Application With Flyout

image

<Shell ...>
     <FlyoutItem Title="Home" ... >
         <ShellContent ... />
     </FlyoutItem>
     <FlyoutItem Title="Single Page" ... >
         <ShellContent ... />
     </FlyoutItem>
</Shell>

Looking at the different combination of FlyoutItem, Tab and ShellContent we can get different page behaviours:

Bottom Tabs

image

<FlyoutItem Title="Bottom Tabs" ... >
     <Tab Title="Home" >
         <ShellContent ... />
     </Tab>
     <Tab Title="Activity" ... >
         <ShellContent ... />
     </Tab>
</FlyoutItem>

Top Tabs

image

<FlyoutItem Title="Top Tabs" ... >
     <Tab Title="Activity" ... >
         <ShellContent Title="Shared" ... />
         <ShellContent Title="Notifications" ... />
     </Tab>
</FlyoutItem>

Tab Sandwich

image

<FlyoutItem Title="Tab Sandwich" ... >
     <Tab Title="Activity" ... >
         <ShellContent Title="Shared" ... />
         <ShellContent Title="Notifications" ... />
     </Tab>
     <Tab Title="Updates" ... >
         <ShellContent Title="Updates" ... />
         <ShellContent Title="Home" ... />
     </Tab>
</FlyoutItem>

As you will have briefly seen, it’s possible to rapidly stand up the basics of an application using a combination of flyouts and tabs to structure your application. In this post we’ve referenced the preview of the next version of Xamarin.Forms Shell, so you can expect that some of the features, particularly around navigation are subject to change in the coming months.

ViewModel to ViewModel Navigation in a Xamarin.Forms Application with Prism and MvvmCross

I’m a big fan of the separation that the Mvvm pattern gives developers in that the user interface is encapsulated in the view (Page, UserControl etc) and that the business logic resides in the ViewModel/Model. When structuring the solution for an application I will go so far as to separate out my ViewModels into a separate project from the views, even with Xamarin.Forms where the views can be defined in a .NET Standard library.

One of the abstractions that this lends itself to is what is referred to as ViewModel to ViewModel navigation – rather than the ViewModel explicitly navigation to a page, or bubbling an event up to the corresponding view to get the view to navigate to the next page, ViewModel to ViewModel navigation allows the ViewModel to call a method such as Navigation(newViewModel) where the newViewModel parameter is either the type of the ViewModel to navigate to, or in some frameworks it may be an actual instance of the new ViewModel.

MvvmCross

Let’s see this in action with MvvmCross first – I’m going to start here because ViewModel to ViewModel navigation is the default navigation pattern in MvvmCross. I’ll start with a new project, created using the MvxScaffolding I covered in my previous post, using MvvmCross in a Xamarin.Forms application. The single view template already comes with a page, HomePage, with corresponding ViewModel, HomeViewModel. To demonstrate navigation I’m going to add a second page and a second ViewModel. Firstly, I’ll add a new class, SecondViewModel, which will inherit from BaseViewModel (a class generated by MvxScaffolding which inherits from MvxViewModel that’s part of MvvmCross).

public class SecondViewModel : BaseViewModel
{
}

Next, I’ll add a new ContentPage called SecondPage (note the convention here that there is a pairing between the page and the ViewModel ie [PageName]Page maps to [PageName]ViewModel)

image

MvvmCross supports automatic registration of pages and ViewModels but it does require that the page inherits from the Mvx base class, MvxContentPage. I just need to adjust the root XAML element from

<ContentPage …

to

<views:MvxContentPage x:TypeArguments="viewModels:SecondViewModel" …

The inclusion of the TypeArguments means that the generic overload of MvxContentPage is used, providing a helpful ViewModel property by which to access the strongly typed ViewModel that is databound to the page.

Now that we have the second page, we just need to be able to navigate from the HomePage. I’ll add a Button to the HomePage so that the user can drive the navigation:

<Button Text="Next" Clicked="NextClicked" />

With method NextClicked as the event handler (here I’m just using a regular event handler but in most cases this would be data bound to a command within the HomeViewModel):

private async void NextClicked(object sender, EventArgs e)
{
     await ViewModel.NextStep();
}

And of course we need to add the NextStep method to the HomeViewModel that will do the navigation. The HomeViewModel also needs access to the IMvxNavigationService in order to invoke the Navigate method – this is done by adding the dependency to the HomeViewModel constructor.

public class HomeViewModel : BaseViewModel
{
     private readonly IMvxNavigationService navigationService;

    public HomeViewModel(IMvxNavigationService navService)
     {
         navigationService = navService;
     }
     public async Task NextStep()
     {
         await navigationService.Navigate<SecondViewModel>();
    }
}

As you can see from this example the HomeViewModel only needs to know about the SecondViewModel, rather than the explicit SecondPage view. This makes it much easier to test the ViewModel as you can provide a mock IMvxNavigationService and verify that the Navigate method is invoked.

Prism

Now let’s switch over to Prism and I’ve used the Prism Template Pack to create a new project. To add a second page I’ll add a SecondPageViewModel, which in the case of Prism inherits from ViewModelBase and requires the appropriate constructor that provides access to the INavigationService. Note that the naming convention with Prism is slightly different from MvvmCross where the ViewModel name is [PageName]PageViewModel (ie both the page and the viewmodel have the Page suffix after the PageName eg SecondPage and SecondPageViewModel)

public class SecondPageViewModel : ViewModelBase
{
     public SecondPageViewModel(INavigationService navigationService) : base(navigationService)
     {
     }
}

I’ll add a new ContentPage called SecondPage but unlike MvvmCross I don’t need to alter the inheritance of this page. Instead what I do need to do is register the page so that it can be navigated to. This is done in the App.xaml.cs where there is already a RegisterTypes method – note the additional line to register SecondPage.

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterForNavigation<NavigationPage>();
     containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
     containerRegistry.RegisterForNavigation<SecondPage, SecondPageViewModel>();
}

Similar to the MvvmCross example, I’ll add a button to the MainPage (the first page of the Prism application created by the template) with code behind to call the NextStep method on the MainViewModel

private async void NextClicked(object sender, EventArgs e)
{
     await (BindingContext as MainPageViewModel).NextStep();
}

Note that because the MainPage just inherits from the Xamarin.Forms ContentPage there’s no property to expose the data bound viewmodel. Hence the casting of the BindingContext, which you’d of course do null checking and error handling around in a real world application.

public async Task NextStep()
{
     await NavigationService.NavigateAsync("SecondPage");
}

The NextStep method invokes the NavigateAsync method using a string literal for the SecondPage – I’m really not a big fan of this since it a) uses a string literal and b) requires the the ViewModel knows about the view that’s being navigated to. So let’s adjust this slightly by changing the way that pages and ViewModels are registered. The RegisterForNavigation method accepts a parameter that allows you to override the navigation path, meaning we can set it to be the name of the ViewModel instead of the name of the page.

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterForNavigation<NavigationPage>();
     containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>(nameof(MainPageViewModel));
     containerRegistry.RegisterForNavigation<SecondPage, SecondPageViewModel>(nameof(SecondPageViewModel));
}

The navigation methods would then look like:

public async Task NextStep()
{
     await NavigationService.NavigateAsync(nameof(SecondPageViewModel));
}

But I think we an improve this further still by defining a couple of extension methods

public static class PrismHelpers
{
     public static void RegisterForViewModelNavigation<TView, TViewModel>(this IContainerRegistry containerRegistry)
         where TView : Page
         where TViewModel : class
     {
         containerRegistry.RegisterForNavigation<TView, TViewModel>(typeof(TViewModel).Name);
     }

    public static async Task<INavigationResult> NavigateAsync<TViewModel>(this INavigationService navigationService)
         where TViewModel : class
     {
         return await navigationService.NavigateAsync(typeof(TViewModel).Name);
     }
}

Using these extension methods we can update the registration code:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterForNavigation<NavigationPage>();
     containerRegistry.RegisterForViewModelNavigation<MainPage, MainPageViewModel>();
     containerRegistry.RegisterForViewModelNavigation<SecondPage, SecondPageViewModel>();
}

And then the navigation code:

public async Task NextStep()
{
     await NavigationService.NavigateAsync<SecondPageViewModel>();
}

The upshot of these changes is that there’s almost no difference between the MvvmCross method of navigation and what can be done with a little tweaking with Prism.

Scaffolding Your Next MvvmCross Xamarin.Forms Project

One of the things I liked about the getting started experience with Prism was that there was a Visual Studio extension that made creating a new project super simple. Whilst I know that MvvmCross doesn’t provide something like that out of the box, I decided to take a look at some of the project/solution templates that the community have created. The Getting Started page on the MvvmCross website does maintain a list of MvvmCross templates but I must confess that some of these are a little dated. I just went through and opened each of the links, and there were only two that seemed to be recent, Mvx Toolkit and MvxScaffolding. I downloaded both extensions and just happened to try out MvxScaffolding first. Here’s a quick summary of creating a new Xamarin.Forms application using MvxScaffolding

Search for Mvx to find the scaffolding templates

image

Basic project details

image

Now we’re into the MvxScaffolding custom dialog – wow, look at how nice this is.

image

I went with the Single Item template – it’s a tad confusing that you have to click on the grey circle to pick each option, rather than clicking the whole card. Next up, pick the platform and which test projects you want generated.

image

I added UWP support, and asked for all the test projects

image

A quick summary before the projects are created

image

The final solution

image

And of course, the running application.

image

This was a bit mind blowing to be honest – the level of detail in this extension was awesome and I was able to generate the runnable application in under a minute. I like the way the projects are separated and that it can generate all the test projects.

Resolving Dependencies In Platform Pages, Renderers, Effects and Elements with Xamarin.Forms and Prism

We’ve been using Prism for a number of our Xamarin.Forms projects and for the most part we rely on the services being injected into our view models but a scenario came up recently where we wanted to access one of our services from within the platform implementation of a renderer. We were using DryIoC and needed to come up with a mechanism to resolve dependencies that had been registered with DryIoC via Prism. I recalled seeing in Brian’s What’s New in Prism 7.1 post that support had been added for the Xamarin.Forms Dependency Resolver and was wondering whether we could use that to allow us to resolve dependencies by calling Resolve on the static DependencyService that Xamarin.Forms exposes. In this post I’m going to walk through creating a simple Prism application, register a service and then retrieve it from the code behind of a UWP page (but the same process applies for any renderer, effect, page or element).

To get started with a new Prism application I’m going to make use of the Prism Template Pack that installs as a Visual Studio Extension and includes a variety of project and item templates. In Visual Studio 2019 when you launch the application you can select Create a New Project and be given the option to search for project templates.

image 

Once you’ve selected the Prism Bank App (Xamarin.Forms) you’ll then be prompted to specify the name and location of the project

image

The final step is a Prism specific dialog that allows you to specify which platforms and what IoC container you want to use

image

In this case we’re going with DryIoC but I think the technique will work equally well if you select AutoFac or Unity. After hitting Create Project our solution is setup with four projects: one for each target platform and a project that contains both our view and view models. 

image

My preference is to separate views and viewmodels further but for the timebeing we’ll leave the project structure as it is. The next step is to create and register the service that we want to retrieve from our platform specific code.

public interface IFancyService
{
     string WelcomeText { get; }
}

public class MyFancyService : IFancyService
{
     public string WelcomeText => "Hello Dependency World!";
}

The MyFancyService needs to be registered with the DI container, which we can do by adding a line to the RegisterTypes method in the App.xaml.cs

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterForNavigation<NavigationPage>();
     containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();

    containerRegistry.Register<IFancyService, MyFancyService>();
}

Let’s switch across to the code behind of the MainPage in the UWP application – note that this page is different from the MainPage that’s in the Xamarin.Forms project which is the page that’s displayed on all platforms. The MainPage in the UWP project is used to host the Xamarin.Forms application when it’s run on Windows. I’m going to add the OnNavigatedTo override method and in it I’m going to attempt to resolve the IFancyService interface using the Xamarin.Forms DependencyService.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
     base.OnNavigatedTo(e);

    var fancy = DependencyService.Resolve<IFancyService>();
}

Running this code we’ll see that the variable fancy is null, meaning that the Resolve method wasn’t able to find any registered implementation of the IFancyService.

image

To fix this, we need to tell Prism to register as a Dependency Resolver, which will mean that the Xamarin.Forms DepedencyService will use the same DI container when resolving instances. This is done by using the overloaded constructor of the PrismApplication class. In the App.xaml.cs of our application, change the call to base to include a second parameter which is set to true.

public App(IPlatformInitializer initializer) : base(initializer, setFormsDependencyResolver: true)
{
}

Running the application now and the fancy variable is set to an instance of the MyFancyService.

image

And there you have it – an easy way to use the Xamarin.Forms DependencyService in conjunction with Prism and DryIoC.

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

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

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 xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              xmlns:vsm="clr-namespace:BuildIt.Forms;assembly=BuildIt.Forms.Core"
              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).

Unboxing Xamarin.Forms Shell in Visual Studio 2019

In my previous post, Unboxing Visual Studio 2019 for Xamarin.Forms, I covered creating a new Xamarin.Forms project in Visual Studio 2019. The Xamarin.Forms project template hasn’t really changed much and the default application you get is the same as what we were seeing in the most recent updates for Visual Studio 2017. However, there are some big updates coming down the line for Xamarin.Forms developers, not the least is Shell, which is covered in the introductory post.

I’m going to take Shell for a bit of a spin, and to do so, I’m going to use the new project templates that are available for download – These will only install into Visual Studio 2019, so if you want to try them out, you’ll first need to install Visual Studio 2019

image

An hours or so later…

image

After installing the new templates I went about creating a new project

image

It seems that the new templates must have completely replaced the previous templates – not a great start, considering I’m likely to want to be able to create a non-shell based Xamarin.Forms application.

image

Ummm…. Where’s the UWP support? Seriously, as if UWP wasn’t failing hard enough as it is, the fact that there doesn’t appear to be UWP support in the initial Shell release it a bid depressing.

After that the new project screens all look familiar, so the next thing we’re looking at is the default solution structure.

image

My first comment (as usual) is that the view models are stuck in the same project as all the UI elements – I consider this to be incredibly bad practice as it means you end up with a mess of dependencies and it’s way to easy to break the separation of concerns between view and view models. Having said that, this is a getting started templates, so I guess if they’d added another project it would probably alienate other developers who prefer to have everything in a single project.

The great thing is that I can select either iOS or Android as my startup project and hit run – a minute or two later after the emulator has started up the app has been deployed and is running.

Side Note: This post actually took me a couple of sessions because I got interrupted and it took a couple of days for me to get back to it. When I did, I accidentally opened the XamShell app I’d created in Visual Studio 2017, where it builds and runs without issue. Of course I don’t have the Shell templates.

Here are a couple of screenshots from the running app – Firstly I love that they’re replaced the Xamarin logo added to the new project, as shown in the splashscreen. Note that this is not actually a splashscreen and that in fact they’re setting the background on the main activitiy. There’s so debate about whether this is best practice, or whether it’s still good to use a splashscreen to improve the perceived boot time of the app.

image

This is the master-details template, so we get things like the burger menu. The main screen includes a basic list and an add button in the navigation bar – pretty stock look and feel.

image

The about page is a little more interesting but again nothing mind-blowing.

image

If we look in the main XamShell project we notice that in addition to the usual App.xaml, which is required for Xamarin Forms, there is now also an AppShell.xaml. At this point I did in fact switch back to Visual Studio 2019 because opening AppShell.xaml in VS2017 seemed to be a bit of a broken experience.

Opening AppShell.xaml the first thing I noticed is that styles have been setup and a combination of implicit and explicit styles defined – yes!!! this is great to see in a template. Next I noticed that two pages have been defined: Browse and About – this confused me as there are actually 4 pages included in the project. On checking the code, it appears that the other pages are dynamically created as needed. The introductory documentation on Shell provides a good overview of the key elements that make up the Shell hierarchy.

My initially impressions are that this is going to be great for jump starting basic mobile applications. I’m interested to see how far this can be taken and how it can handle more complex navigation patterns and applications. I’ll explore further the various aspects of Shell but I’d encourage all Xamarin Forms developers to give Shell a chance – let’s see whether this can be made into something amazing by providing constructive feedback to the XF team.


----------

Contact Built to Roam for more information on building cross-platform applications

----------

Unboxing Visual Studio 2019 for Xamarin.Forms

I’ve just installed the preview for Visual Studio 2019 and wanted to share the experience of creating a new Xamarin.Forms application.

Firstly, the startup screen. Whilst I’m disappointed not to have the news feed, the new startup screen gives you a quick launching pad for whatever it is you want do in VS2019.

image

Let’s go with “Create a new project”. The search/filtering works well to quickly find the right project template

image

Now let’s provide some generic project information.

image

Ah and now we’re back to a familiar dialog for creating Xamarin.Forms applications. Hooray!!! there’s no option to use a shared library any more – good riddance. As you’ll see we get a .NET Standard 2.0 project where our XF pages and other logic will go.

image

And now we have the usual solution structure for an out of the box XF application containing the project that’ll house the pages (ie VS2019XFProject) and then head projects for iOS, Android and UWP.

image

Let’s hit run and check out the newly created project – notice I picked the Master-Detail template early so we get a basic layout with a hamburger button in top left.

image

And that’s it. BTW the chrome around the edge of the coding window seems to be progressively shrinking with each progressive release of Visual Studio. Eventually it’ll be carved back to what Visual Studio Code offers.


----------

Contact Built to Roam for more information on building cross-platform applications

----------

Screenshots for Xamarin.Forms with MvvmCross Article

A while ago I wrote an article for Visual Studio magazine that details getting started with Xamarin.Forms and MvvmCross. Whilst some things have changed since then, the process for getting started is still basically the same. To verify this process I followed the article and took screenshots along the way – these mostly correspond to the screenshots that are in the article, with a couple of extras thrown in to ensure good coverage of the steps. Please follow the instructions in the article Build a Xamarin.Forms Application with MvvmCross:

Create the new solution

image

Pick the Blank template using the .NET Standard library

Note that the order of the Code Sharing Strategy has changed, placing .NET Standard as the default (about time!!!)

image

Add a new Core library

image

Add reference to the Core library to each project

image

Update existing NuGet packages

image

Add reference to MvvmCross to ALL projects

image

Add reference to MvvmCross.Forms to all EXCEPT the Core project

image

Add App class to Core project and add necessary using statements

image

Update the MainPage to use the MvxContentPage as base class and in Views namespace

image

Don’t forget to update the code-behind file – Remove base class and update namespace

image

UWP: Change MainPage to inherit from MvxFormsWindowsPage and fix using statement

image

UWP: The updated MainPage

image

UWP: The updated MainPage code-behind file

image

UWP: Update the App class to inherit from ProxyMvxApplication

image

UWP: The ProxyMvxApplication class and the App code-behind

Note: I cheated here for the screenshot and had these in the same file. I would recommend having the ProxyMvxApplication in a separate file

image

Android: Error when building

image

Android: Add reference to Mono.Android.Export

image

Android: Change MainActivity to RootActivity and inherit from MvxFormsAppCompatActivity

image

iOS: Update AppDelegate to inherit from MvxFormsApplicationDelegate

image


I hope these screenshots help anyone who runs into issues getting started when following the Visual Studio Magazine article



----------

Contact Built to Roam for more information on building cross-platform applications

----------

Getting Started with Xamarin.Forms and Unit Testing with xUnit and Moq (II)

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries
Platform Specific Resources with OnPlatform, Device Customization using OnIdiom
Unit Testing with xUnit and Moq

One of the hardest aspects of testing is implementing and executing platform specific unit tests. As I was putting together a post covering platform specific testing I got side tracked looking at the use of Moq, which I posted about previously. On closer inspection of the csproj of the xUnit test project that I created as part of that post, the target framework is set to netcoreapp2.1. In order to test platform specific features I need to adjust the csproj to be multi-targeted covering android, ios and uwp. By making the test project multi-targeted the code can access platform specific APIs in order to be able to verify the platform specific code in our Core library.

<TargetFrameworks>netcoreapp2.1;Xamarin.iOS10;MonoAndroid90;uap10.0.16299</TargetFrameworks>

If we compare the target frameworks with those used by the Core project of our application, we can see that we have netcoreapp2.1 instead of netstandard2.0. In order to take advantage of the xUnit test runner, the test project does need to target netcoreapp2.1. We don’t really need to add netstandard2.0, since we don’t have a test runner that is only based on netstandard2.0 and our application never actually runs as a .NET Standard application (i.e. it runs as an iOS, Android or UWP application)

After changing the target frameworks the test project doesn’t build for a couple of reasons:

- The Visual Studio xUnit test runner isn’t compatible with the platform specific target frameworks

- xUnit has a platform specific test running that needs to be referenced. I’ll cover the platform specific test runners in future posts

The csproj of the test project should be updated to selectively include package references:

<PropertyGroup>
   <TargetFrameworks>netcoreapp2.1;Xamarin.iOS10;MonoAndroid90;uap10.0.16299</TargetFrameworks>
  <IsNetCoreApp>$(TargetFramework.StartsWith('netcoreapp'))</IsNetCoreApp>
</PropertyGroup>

<ItemGroup Condition=" '$(IsNetCoreApp)' != 'true' ">
   <PackageReference Include="xunit.runner.devices" Version="2.4.48" />
   <PackageReference Include="UnitTests.HeadlessRunner" Version="2.0.0" />
</ItemGroup>

<ItemGroup Condition=" '$(IsNetCoreApp)' == 'true' ">
   <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
   <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0">
   <PrivateAssets>all</PrivateAssets>
   <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
   </PackageReference>
</ItemGroup>

<ItemGroup>
   <PackageReference Include="xunit" Version="2.4.0" />
</ItemGroup>

Even after changing the package references to make them conditional, there were issues referencing the stable release of Moq. Unfortunately the current release of Moq uses some features around reflection that aren’t supported by all platforms, and whilst it’s compatible with netcoreapp2.1, it’s not compatible with netstandard2.0. I went looking for other mocking options and almost immediately came across the work being done on the next iteration of Moq – this is a major change that does more of the heavy lifting at compile time, rather than dynamically at runtime.

At the time of writing, the next release for Moq is currently available only as source code from https://github.com/moq/moq

Once the source code has been built, the assemblies can be added as a direct reference to the test project.

<ItemGroup>
   <Reference Include="Moq">
     <HintPath>..\Library\Moq\Moq.dll</HintPath>
   </Reference>
   <Reference Include="Moq.Sdk">
     <HintPath>..\Library\Moq\Moq.Sdk.dll</HintPath>
   </Reference>
   <Reference Include="Stunts">
     <HintPath>..\Library\Moq\Stunts.dll</HintPath>
   </Reference>
</ItemGroup>

<ItemGroup Condition="'$(DesignTimeBuild)' == 'true'">
   <Analyzer Include="..\Library\Moq\Stunts.dll" />
   <Analyzer Include="..\Library\Moq\Stunts.Sdk.dll" />
   <Analyzer Include="..\Library\Moq\Roslyn.Services.Test.Utilities.dll" />
   <Analyzer Include="..\Library\Moq\Stunts.CodeAnalysis.dll" />
   <Analyzer Include="..\Library\Moq\Stunts.CodeFix.dll" />
   <Analyzer Include="..\Library\Moq\netstandard.dll" />
   <Analyzer Include="..\Library\Moq\Moq.Sdk.dll" />
   <Analyzer Include="..\Library\Moq\Moq.CodeAnalysis.dll" />
   <Analyzer Include="..\Library\Moq\Moq.CodeFix.dll" />
</ItemGroup>

In addition to assembly references, the Moq libraries are also added as Analyzers – this is to allow for the design time generation of code. Which brings me to the next step which is to adjust our test case to make use of the new Moq syntax. Currently the new version of Moq requires the manual inclusion of Mock.cs and Mock.overloads.cs (content files in the output folder that are generated by building the Moq source code) which include a bunch of helper methods that you’ll need.

The basic process for testing with a mock hasn’t changed – you still need to create and setup your mock entities, invoke a series of methods and then verify actual vs expected output:

[Fact]
public async Task AuthenticateTest()
{
     var credentialsMock = Mock.Of<ICredentialService>();
#pragma warning disable CS4014 // Don't await - we're calling Authenticate so that we can train the Mock to return a specific value
     credentialsMock.Authenticate().Returns(()=>Task.FromResult("SomeRandomAccessToken"));
#pragma warning restore CS4014

    var mainViewModel = new MainViewModel(
         null,
         null,
         credentialsMock);
     Assert.True(await mainViewModel.Authenticate());
}

I’ve bolded the lines that are worth reviewing in the amended test method:

- Where previously we created a new instance of Mock<ICredentialService>, now we’re using the method Mock.Of<ICredentialService>.

- Previously we called Setup to define the mocked behaviour. Now, we call the actual method we want to mock and then use the Returns method to define what the behaviour should be. Since we actually want to mock the Task that is returned by the Authenticate method, it’s important that we don’t attempt to await it. Hence the #pragma statements

This code will not currently compile, showing an error stating that there’s currently no mock implementation on ICredentialService. This error is generated by the Moq analysers we added to the csproj.

image

Expanding the help tooltip

image

Following the tooltip suggestion we can go ahead and create the mock for the ICredentialService. This will be added to a “Mocks” folder and appropriately named ICredentialServicesMock.

With that we can go ahead and run the test case.

image

In this post we’ve taken a quick look at getting started with the next version of Moq. We’ll take this further in the next post to cover running platform tests.

Intercepting the Android Software Back Button in Xamarin.Forms

Recently an issue was raised on MvvmCross that claimed there was an issue intercepting the back button in a Xamarin.Forms + MvvmCross application running on Android. I spent a bit of time investigating the issue as I didn’t believe MvvmCross was doing anything that would prevent an application from intercepting the back button. In this post I’ll walk through my investigation and demonstrate a solution that I came up with. Just for clarity, the issue was referring to intercepting the software back button that appears in the navigation bar.

In the comments someone had referenced a solution proposed by Udara Alwis (https://theconfuzedsourcecode.wordpress.com/2017/03/12/lets-override-navigation-bar-back-button-click-in-xamarin-forms/) which states that the OnOptionsItemSelected method can be overridden in the Activity that hosts the Xamarin.Forms application. Further comments indicated that this solution didn’t work for a Xamarin.Forms application that was using MvvmCross. My starting point was to of course validate this assertion. Using the Playground sample in the MvvmCross source code I attempted to override the OnOptionsItemSelected method in the MainActivity of the Android application. I ran the application and sure enough, the OnOptionsItemSelected method does not get invoked when tapping the software back button.

Having validated that the MvvmCross Playground was indeed broken, I next wanted to test to see if it was an issue with Xamarin.Forms itself. To do this, I started by creating a new Xamarin.Forms application (I’m just going to build for Android, since this is just a sample).

image

The Blank application template comes with a single page, MainPage. I added a second page to the application:

image

Onto the MainPage I added a Button and in the Clicked event handler added code to navigate to the page I just added:

private async void Button_Clicked(object sender, EventArgs e)
{
     await Navigation.PushAsync(new Page1());
}

In order to get the navigation bar to appear, I changed the App constructor to make use of a NavigationPage:

public App()
{
     InitializeComponent();

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

Lastly, I needed to add the OnOptionsItemSelected override to the MainActivity.

public override bool OnOptionsItemSelected(IMenuItem item)
{
     return base.OnOptionsItemSelected(item);
}

Unfortunately, after doing all this, the OnOptionsItemSelected method was still not called. Looks like the issue sits with Xamarin.Forms, so it’s time to start trawling through the source code.

After an initial inspection it appears that the FormsAppCompatActivity does override the OnOptionsItemSelected method, but that doesn’t explain why overriding it in my application wouldn’t work. However, further inspection revealed that the NavigationPageRenderer (the renderer for the NavigationPage) implements the IOnClickListener interface and registers itself with the ActionBar (which corresponds to the navigation bar). Doing this prevents the call to the OnOptionsItemSelected method, which is why we were not seeing it called.

I figured that I would try extending the default renderer and provide my own implementation of the IOnClickListener interface:

[assembly: ExportRenderer(typeof(NavigationPage), typeof(HackBackButton.CustomNavigationPageRenderer))]
namespace HackBackButton
{
     public class CustomNavigationPageRenderer : NavigationPageRenderer, IOnClickListener
     {
         public CustomNavigationPageRenderer()
         {
         }

        public CustomNavigationPageRenderer(Context context) : base(context)
         {
         }

        public new void OnClick(Android.Views.View v)
         {
             Element?.PopAsync();
         }
    }
}

This works and the OnClick method is invoked when the software back button is tapped. Of course, we then need to route this to the current page so that it can decide if it should allow the back navigation.

Turns out that it’s nothing to do with MvvmCross and that the issue lie entirely with Xamarin.Forms. There needs to be a better way to intercept the back navigation. Someone has already listed a issue with Xamarin.Forms, so add a comment and make sure this issue gets some attention.

Getting Started with Xamarin.Forms and Unit Testing with xUnit and Moq

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries
Platform Specific Resources with OnPlatform, Device Customization using OnIdiom

When we kicked off this project we separated out the business logic from the user interface into Core and UI projects respectively. The main aim was to ensure clear separation of context and to allow for the business logic to be developed, and more importantly, tested, independently of the UI. In this post we’ll get started with unit testing our Core library using xUnit. I’ll also touch on using the mocking library, Moq, to make our testing lives easier.

To get started we’ll add another project to our solution, this time based on the xUnit Test Project (.NET Core) from the Add New Project dialog.

image

If we inspect what gets added we’ll see that it’s a regular single targeted project with references to xUnit and the Microsoft test library.

image

After creating the project, don’t forget to do the obligatory NuGet package update. If you open the UnitTest1 class you can right-click within the Test1 method and select Run Test(s).

image

When you execute tests within Visual Studio you can see the execution progress in the Output window. If it doesn’t automatically switch, you may need to select Tests for the “Show output from” dropdown.

image

Before we can write tests for our Core library, we need to add a reference to the Core library to the Testing library.

image

Now we’re ready to start creating our own tests (you can delete UnitTest1.cs since we won’t be needing it). Everyone has their own naming convention and structure for testing library. I tend to mirror the layout of the project I’m testing. So in this case I've created a ViewModels folder within the test project and have created a class MainViewModelTest class.

At this point I’m also going to add a reference to Moq (https://www.nuget.org/packages/Moq) which I’ll use as part of the test method

public class MainViewModelTest
{
     [Fact]
     public async Task AuthenticateTest()
     {
         var credentialsMock = new Mock<ICredentialService>();
         credentialsMock.Setup(x => x.Authenticate()).Returns(() => Task.FromResult("SomeRandomAccessToken"));

        var mainViewModel = new MainViewModel(
             new Mock<IMvxLogProvider>().Object,
             new Mock<IMvxNavigationService>().Object,
             credentialsMock.Object);
         Assert.True(await mainViewModel.Authenticate());
     }
}

Here I’ve kept the AuthenticateTest method relatively straight forward – I created a mock instance of the ICredentialService which returns a predefined access token; this is then used along with two other mock objects when creating the MainViewModel instance. I then assert that calling the Authenticate returns true (i.e. because the Authenticate method on the ICredentialService instance returns a not-null access token).

Right-click within this test method to run the test returns a positive outcome in the Output window. You can also run and see the results of running test cases via the Test Explorer window.

image

And that’s it, you can now write as many test cases as you feel are necessary for your services, viewmodels and other Core classes.

Getting Started with Xamarin.Forms and Device Customization using OnIdiom

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries
Platform Specific Resources with OnPlatform

Last post I covered how to use OnPlatform to tailor resources and styles based on the target platform. However, there is an alternative dimension you can tailor the layout of your application and that’s using OnIdiom. If you look at the definition of the OnIdiom class you can see that it allows you to define different values for Phone, Tablet, Desktop, TV and Watch.

image

To use this in XAML is very similar to using OnPlatform:

<Label>
     <Label.Text>
         <OnIdiom x:TypeArguments="x:String">
             <OnIdiom.Phone>Hello from a phone app</OnIdiom.Phone>
             <OnIdiom.Desktop>Hello from a desktop app</OnIdiom.Desktop>
         </OnIdiom>
     </Label.Text>
</Label>

As you can see from the code snippet this provides different string values for when the application is run on a phone vs being run on a desktop.

Note: Tablet only works well for iOS and Android. Xamarin.Forms running on UWP currently doesn’t distinguish between Windows running in desktop or tablet mode, and as such will always use the Desktop idiom values.

Getting Started with Xamarin.Forms and Platform Specific Resources using OnPlatform

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles, Resource Dictionaries

In previous posts we’ve looked at using resources and then styles and resource dictionaries in order to manage the style of elements throughout our application. Whilst Xamarin.Forms provides an out-of-the-box cross platform experience, the reality is that if you don’t tweak the layout a bit for each platform, your application is going to look very generic, and not in a good way. In this post we’ll look at some of the different ways that you can adjust layout based on which target platform the application is running on.

The starting point is to look at an individual element, such as a Label, and how an individual property can be adjusted for different platforms using an OnPlatform element.

<Label Text="Hello World!">
     <Label.FontAttributes>
         <OnPlatform x:TypeArguments="FontAttributes">
             <On Platform="Android" Value="Italics"/>
             <On Platform="iOS" Value="None"/>
             <On Platform="UWP" Value="Bold"/>
         </OnPlatform>

     </Label.FontAttributes>
</Label>

In this example instead of supplying a value for the FontAttributes attribute we’ve expanded into long form using a Label.FontAttributes element. Nested within this element we create an OnPlatform element, supplying the TypeArguments attribute to indicate what Type of value the OnPlatform is going to produce. Within the OnPlatform element we then have an On element for each platform we want to specify a value for.

Since we’re not a big fan of having literals specified for an individual element, and even more so when doing per-platform styling, we can also define resources using the OnPlatform syntax:

<OnPlatform x:Key ="FeatureColor" x:TypeArguments="Color">
     <On Platform="Android" Value="Red"/>
     <On Platform="iOS" Value="Green"/>
     <On Platform="UWP"  Value="Blue"/>
</OnPlatform>

This defines a resource, FeatureColor, within a ResourceDictionary, with different colors defined for each of the three platforms.

As you can see, defining values for each platform can start to add a lot of bloat to your XAML. A work around for this is to use a similar technique that we’ve discussed previously where we include files on a per platform basis. For resources this requires a bit of fiddling, so there are a few steps involved. We need to start with the csproj for the UI project and adjust the first ItemsGroup to remove all XAML files that are within the Platforms folder. Next we need to selectively add back the XAML files based on what the target platform is. The bold lines in the following XAML from the csproj file indicate these changes.

<ItemGroup>
   <Compile Remove="Platforms\**\*.cs" />
   <None Include="Platforms\**\*.cs" />
   <EmbeddedResource Remove="Platforms\**\*.xaml" />
   <None Include="Platforms\**\*.xaml" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
   <Compile Include="Platforms\Netstandard\**\*.cs" />
   <EmbeddedResource Include="Platforms\Netstandard\**\*.xaml" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('uap')) ">
   <Compile Include="Platforms\Uap\**\*.cs" />
   <EmbeddedResource Include="Platforms\Uap\**\*.xaml" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) ">
   <Compile Include="Platforms\Ios\**\*.cs" />
   <EmbeddedResource Include="Platforms\Ios\**\*.xaml" />
</ItemGroup>

<ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid')) ">
   <Compile Include="Platforms\Android\**\*.cs" />
   <EmbeddedResource Include="Platforms\Android\**\*.xaml" />
</ItemGroup>

Next we need to create platform specific XAML files. I simply copied the LiteralResources.xaml and LiteralResources.xaml.cs into each of the Platform folders and renamed both the files and the class name to PlatformLiteralResources. In my case the project structure looks like the following:

image

You’ll notice that the PlatformLiteralResources.xaml is only showing under the Netstandard – this appears to be a bit of a bug in Visual Studio as the file exists and should appear in the project structure for all the platforms. The only thing left to do is define some platform resources and to link the PlatformLiteralResources class into the resource dictionary hierarchy:

PlatformLiteralResources

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:res="clr-namespace:StrataPark.UI.Resources"
                      x:Class="StrataPark.UI.Resources.PlatformLiteralResources">
     <ResourceDictionary.MergedDictionaries>
         <res:LiteralResources />
     </ResourceDictionary.MergedDictionaries>
    <x:Double x:Key="DefaultLabelFontSize">24</x:Double>
</ResourceDictionary>

StyleAndTemplateResources

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:res="clr-namespace:StrataPark.UI.Resources"
                     x:Class="StrataPark.UI.Resources.StyleAndTemplateResources">
     <ResourceDictionary.MergedDictionaries>
         <res:PlatformLiteralResources />
     </ResourceDictionary.MergedDictionaries>

    <!-- Other resources -->
</ResourceDictionary>

Note that the hierarchy is now App.xaml >> StylesAndTemplateResources >> PlatformLiteralResources >> LiteralResources.

And there you have it, you can now define platform specific literals in the PlatformLiteralResources xaml file without worrying about using the OnPlatform element.

Getting Started with Xamarin.Forms and Resource Dictionaries

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross, Resources and Styles

Last post, on Resources and Styles, we discussed how resources, such as styles, can be defined at different levels within the view hierarchy. In this post we’re going to cover using resource dictionaries to better manage resources. Let’s start by recapping how resources can be defined by starting with a basic application level resource, which are resources that can be accessed anywhere in the application.

<Application.Resources>
     <Thickness x:Key="LeftRightMargin">48,0</Thickness>

As we go down the view hierarchy, we can define resources at a page level, which are resources that will only be accessible to elements on the same page

<Page.Resources>
     <Thickness x:Key="LeftRightMargin">36,0</Thickness>

A couple of things to note here – firstly we’re defining a resource with the same name as at the application level, which means we’re going to be overriding the resource value but only for this page. It’s also worth nothing that we’re using Page.Resources, despite the type of the page being ContentPage (for a normal Xamarin.Forms page) or MvxContentPage (for an MvvmCross page). This is acceptable since Page is the base class for both ContentPage and MvxContentPage, meaning that we can use it to reference the Resources property. It’s up to you whether you use Page.Resources or ContentPage.Resources, or even MvxContentPage.Resources, as they all reference the same property.

We can continue down the hierarchy, defining resources at either the container, or element level. As before, the resources are only accessible to the element and it’s children where the resource is defined.

<Grid.Resources>
     <Thickness x:Key="LeftRightMargin">24,0</Thickness>

<Label.Resources>
     <Thickness x:Key="LeftRightMargin">12,0</Thickness>

Now that we've seen how we can define resources at any level in the view hierarchy but currently we’re storing all our application level resources into the App.xaml, which overtime is going to get quite hard to manage. One approach to make resources easier to manage is to create separate resource dictionaries for different types of resources. My preference is to have a dictionary that contains literals such a colours, strings, Thickness, converters, and another resource dictionary that has styles and templates.

Let’s start by creating a separate dictionary and linking it to our App.xaml. Unfortunately Visual Studio doesn’t currently come with an item template for a ResourceDictionary for Xamarin.Forms. I’m going to create a folder called Resources within the UI project, open the folder in File Explorer and create a new file called StyleAndTemplateResources.xaml.

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

    <!-- Add all Style and Template resources here -->
    <Style TargetType="Label"  x:Key="SomeLabelStyle" />
</ResourceDictionary>

This needs to be referenced in App.xaml to ensure the resources are loaded at application startup.

<Application.Resources>
     <ResourceDictionary Source="Resources\StyleAndTemplateResources.xaml"/>
</Application.Resources>

Note that we’re using the new syntax supported in Xamarin.Forms v3+ where we do not need to include the MergedDictionaries tag and we can load the ResourceDictionary based on the path to the XAML. This means that we don’t need to specify the Class attribute in the XAML for the ResourceDictionary; nor do we need the code behind file.

Let’s also add another ResourceDictionary which will contain our literals. This will follow the same structure as the StyleAndTemplateResources.xaml but called LiteralResources.xaml, and we need to update the App.xaml.

<Application.Resources>
    <!-- This will NOT work -->
     <ResourceDictionary Source="Resources\LiteralResources.xaml"/>
     <ResourceDictionary Source="Resources\StyleAndTemplateResources.xaml"/>
</Application.Resources>

As the comment in the XAML states, adding the two resource dictionaries in parallel like this in the App.xaml will not work. At runtime you can expect a XAML parsing error, stating that resources defined in LiteralResources can’t be found when loading resources in StyleAndTemplateResources.

image

This is because both resource dictionaries are loaded independently and then merged into the resource dictionary for the application. In order to reference resources from LiteralResources, it needs to be loaded first, followed by StyleAndTemplateResources. You should be able to do this by chaining resource dictionaries as follows (Warning: this currently does not work!):

App.xaml

<Application.Resources>
    <ResourceDictionary Source="Resources\StyleAndTemplateResources.xaml"/>
< /Application.Resources>

StyleAndTemplateResources

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
     <ResourceDictionary.MergedDictionaries>
         <ResourceDictionary Source="Resources\LiteralResources.xaml"/>
    </ResourceDictionary.MergedDictionaries>

    <!-- Other resources -->
</ResourceDictionary>

So, the question is – if this doesn’t work, what do you have to do? Well the good news is that we’re on the right track using a hierarchy of dictionaries. Unfortunately due to some issues with Xamarin.Forms, we can’t use the simplified form, instead we need to make sure that each resource dictionary has a Class attribute and a code behind file, and we need to explicitly use the MergedDictionaries element.

Start by creating code behind files for both resource dictionaries:

public partial class LiteralResources
{
     public LiteralResources()
     {
         InitializeComponent();
     }
}
public partial class StyleAndTemplateResources
{
     public StyleAndTemplateResources()
     {
         InitializeComponent();
     }
}

Next, we’ll update App.xaml and the other resource xaml files to define the Class attribute and fix the hierarchy:

LiteralResources.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                      x:Class="StrataPark.UI.Resources.LiteralResources">
     <Thickness x:Key="LeftRightMargin">48,0</Thickness>

    <x:Double x:Key="DefaultLabelFontSize">24</x:Double>
     <Color x:Key="FeatureColor">Green</Color>
</ResourceDictionary>

StyleAndTemplateResources.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="
http://xamarin.com/schemas/2014/forms"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     xmlns:res="clr-namespace:StrataPark.UI.Resources"
                     x:Class="StrataPark.UI.Resources.StyleAndTemplateResources">
     <ResourceDictionary.MergedDictionaries>
         <res:LiteralResources />
     </ResourceDictionary.MergedDictionaries>

    <Style x:Key="FeatureLabelStyle" TargetType="Label">
         <Setter Property="TextColor" Value="{StaticResource FeatureColor}"/>
         <Setter Property="FontSize" Value="{StaticResource DefaultLabelFontSize}"/>
     </Style>

    <Style TargetType="Label" BasedOn="{StaticResource FeatureLabelStyle}"/>
</ResourceDictionary>

App.xaml

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="
http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              xmlns:res="clr-namespace:StrataPark.UI.Resources"
              x:Class="StrataPark.UI.App">
     <Application.Resources>
         <ResourceDictionary>
             <ResourceDictionary.MergedDictionaries>
                 <res:StyleAndTemplateResources />
             </ResourceDictionary.MergedDictionaries>
         </ResourceDictionary>
    </Application.Resources>
</Application>

And there you have it – resources are separated out for easier maintainability.

Getting Started with Xamarin.Forms with Resources and Styles

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross
Presentation Attributes in MvvmCross

In this post we’re going to look at how you can adjust the default style for the controls that you use within your Xamarin.Forms application. To get started, let’s look at how you might change the colour of a basic Label – there are a couple of options but all start with setting the TextColor property:

<Label TextColor="#0F0" />
<Label TextColor="#00FF00" />
<Label TextColor="Green" />

A lot of applications will have all sorts of layout properties set explicitly in the page XAML. Unfortunately this becomes increasingly hard to manage as the application grows. Imagine having 10+ pages all with the colour of elements set explicitly and then you want to change the theme of the application – this would require going through every element to make sure every colour is correct.

An alternative is to extract various properties into static resources where they can be managed at an application, page or even control level. Let’s look at defining an application resource in the App.xaml file in the UI project.

<Application xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="StrataPark.UI.App">
     <Application.Resources>
         <Color x:Key="FeatureColor">Green</Color>
    </Application.Resources>
</Application>

In this case we’ve defined a Color resource with a Key of FeatureColor. This can be used anywhere in the application using the Key.

<Label TextColor="{StaticResource FeatureColor}" />

Extract properties into resources can be done for all sorts of values such as strings, colours, margins etc. Not all resources need to be defined at an application level. Resources can be added to the Resources dictionary of a Page or even a control (for example a Grid) – this limits the scope of that resource to the element where the resource is defined, and it’s children. For example, adding a resource to the Resources dictionary of a Page means that the resource is available to all elements on that page but not to elements on other pages within the application.

Note: It may seem simpler to add all resources to the Application Resources dictionary – just be aware that there is a performance cost associated with this as all resources will need to be loaded when the application is started up. Depending on the number and complexity of the resources, this can have a negative impact on the startup time for your application.

Returning to the example of setting the colour of the text of a Label, creating the FeatureColor resource makes it easy to apply the same colour to a number of Label elements and then to be able to change their colour in one place. However, there are two issues here:

- What if we want to be able to set other common properties across all these Label elements? For example, we might want to set FontSize.

- We still have to explicitly set the TextColor on each Label – it would be great if the colour could be set automatically on all Label elements.

The answer to both of these is to define a Style, which you can think of as a collection of property setters, applied by setting the Style property of an element. Let’s start with the first issue where we want to be able to set the FontSize as well as the colour. To do this we’ll create a Style called FeatureLabelStyle, again in the App.xaml so it can be used throughout the application.

<x:Double x:Key="DefaultLabelFontSize">24</x:Double>
<Color x:Key="FeatureColor">Green</Color>

<Style x:Key="FeatureLabelStyle" TargetType="Label">
     <Setter Property="TextColor" Value="{StaticResource FeatureColor}"/>
     <Setter Property="FontSize" Value="{StaticResource DefaultLabelFontSize}"/>
</Style>

Note that we still have a resource called FeatureColor which specifies the colour of the Label, and we have another resource that defines the size to be used for the FontSize. These are combined into the FeatureLabelStyle, which can then be applied by setting the Style property.

<Label Style="{StaticResource FeatureLabelStyle}" />

Moving now to the second issue, which is how we can apply a Style to all Label elements. Currently the Style we have defined has a Key assigned to it, making it an explicit Style, since the Key has to be used in order to explicitly specify the Style. In order to apply it to all elements we need to define an implicit style, a Style with no Key.

<Style TargetType="Label" BasedOn="{StaticResource FeatureLabelStyle}"/>

The implicit Style will be automatically applied by default to all Label elements. Note that we have based the implicit Style on the previously defined explicit style – this is best practice as it means we can take advantage of Style inheritance. For example you might have a base explicit Style that defined the default colour for all Label styles.

And there you have it, a quick overview of using Resources and Styles within your Xamarin.Forms application.

Getting Started with Xamarin.Forms and Presentation Attributes in MvvmCross

Previous posts in this sequence on Getting Started with Xamarin.Forms:
Multi-Targeting in Visual Studio, SDK Versions, MvvmCross, Authenticating with ADAL
Refactoring MvvmCross and Services, Effects, Navigation with MvvmCross

The great thing about MvvmCross is that it provides a minimal effort approach to things like navigation. However, there are times when you want to override the navigation model. For example you might want a page to appear as a modal page instead of a regular page. MvvmCross allows you to do this by overriding the default way that a page is presented, which is controlled by a presentation attribute applied to the page. Out of the box, MvvmCross comes with a number of presentation attributes that you can use to control how a page is rendered. By default, if you attempt to navigate to a page, MvvmCross assumes that you just want to navigate to that page using the Xamarin.Forms PushAsync method. This is the same as if you had attributed the page with the MvxContentPagePresentation attribute e.g.

[MvxContentPagePresentation]
public partial class MainPage

Note: By default you do not need to attribute each page with an attribute if you just want to navigate to the page. You can use the MvxContentPagePresentation attribute to override the back stack (i.e. using a combination of the NoHistory and WrapInNavigation properties)

I’m going to change the ProfilePage to appear as a modal page. The only change I need to make is to add the MvxModalPresentation attribute to the ProfilePage class.

[MvxModalPresentation]
public partial class ProfilePage

Now when I run the application the Profile Page will appear as a modal page. Unfortunately there is currently no way to dismiss the modal page, so the application will get stuck with the ProfilePage displayed. To fix this, let’s add a button to the ProfilePage that will be used to close the modal page. Again, I’ll start by showing how to close the page in code behind using the Xamarin.Forms navigation construct:

<Button Text="Close" Clicked="CloseClicked"/>

private async void CloseClicked(object sender, System.EventArgs e)
{
    await Navigation.PopModalAsync();
}

Note: Xamarin.Forms distinguishes between closing a modal page using PopModalAsync vs closing a regular page using PopAsync.

Of course, we’d prefer to have the button linked to a command in the view model that can be used to close the corresponding page. The code for the Button and the ProfileViewModel are as follows.

<Button Text="Close" Command="{Binding CloseCommand}"/>


public class ProfileViewModel: MvxNavigationViewModel
{
     private IMvxCommand closeCommand;

    public ProfileViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService) : base(logProvider, navigationService)
     {
     }

    public IMvxCommand CloseCommand => closeCommand ?? (closeCommand = new MvxAsyncCommand(()=>NavigationService.Close(this)));
}

Note: The ProfileViewModel inherits from the MvxNavigationViewModel so that it can access the NavigationService.

The NavigationService exposes a Close method which will close the current view model, and the corresponding page. This code is the same irrespective of whether the ProfilePage is shown as a regular or a modal page.

There you have it – you can easily override how pages are displayed in your Xamarin.Forms application using presentation attributes in MvvmCross. There are other attributes that come with MvvmCross to allow you easily display pages in master-detail, tabbed and carousel layouts.

image

In addition to the built in attributes, you can override the MvxPagePresentation attribute and add your own custom layout logic for how pages are presented.

Getting Started with Xamarin.Forms and Navigation with MvvmCross

Previous posts in this sequence:
Getting Started with Xamarin.Forms and Multi-Targeting in Visual Studio
Getting Started with Xamarin.Forms and SDK Versions
Getting Started with Xamarin.Forms with MvvmCross
Getting Started with Xamarin.Forms and Authenticating with ADAL
Getting Started with Xamarin.Forms, Refactoring MvvmCross and Services
Getting Started with Xamarin.Forms and Effects

Xamarin.Forms has a built in mechanism for navigating between pages. Let’s start with navigating from the MainPage to a new ProfilePage, based on the Content Page item template, added to the Pages folder of the UI project.

image

To trigger the navigation, we’ll add a new Button to the MainPage and add logic to navigate to the ProfilePage.

<Button Text="Profile" Clicked="ProfileClicked"/>

private async void ProfileClicked(object sender, System.EventArgs e)
{
     await Navigation.PushAsync(new ProfilePage());
}

Navigation between pages includes adding a back button and handles any hardware back button

imageimage

The limitation with the built in navigation model for Xamarin.Forms is that it is triggered in the UI layer (i.e. in the code behind of the MainPage). Using MvvmCross we can move the navigation logic into the domain of the view model, meaning it can be tested independently of the UI.

To do this, we need to add a ProfileViewModel class, which corresponds to the ProfilePage.

image

The ProfileViewModel should inherit from MvxViewModel:

public class ProfileViewModel: MvxViewModel
{
}

The ProfilePage also needs to be updated to inherit from MvxContentPage.

We can now update the MainViewModel to expose a command that can be used to navigate to the ProfileViewModel:

private IMvxCommand profileCommand;
public IMvxCommand ProfileCommand => profileCommand ?? (profileCommand = new MvxAsyncCommand(ShowProfile));
private async Task ShowProfile()
{
     var navService = Mvx.IoCProvider.Resolve<IMvxNavigationService>();
     await navService.Navigate<ProfileViewModel>();

}

The code in the MainPage can now be changed to connect the button to the ProfileCommand in MainViewModel.

<Button Text="Profile" Command="{Binding ProfileCommand}"/>

Navigation is now triggered from the ProfileViewModel.

Refactoring to use MvxNavigationViewModel

The code added to the ShowProfile method uses the Mvx IoC container to look up the IMvxNavigationService. This isn’t great as it is a hidden dependency. An alternative would be to add the IMvxNavigationService as a parameter to the MainPage constructor, which would be injected automatically

public MainViewModel(IMvxNavigationService navigationService, ICredentialService credentialService)

Adding the IMvxNavigationService as a parameter in the constructor means that the view model has to maintain a reference to it until it’s used by the ShowProfile method. Alternatively, we can change the base class to use the MvxNavigationViewModel which already exposes a NavigationService property.

public MainViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService, ICredentialService credentialService) : base(logProvider, navigationService)

and the updated ShowProfile method is:

private async Task ShowProfile()
{
     await NavigationService.Navigate<ProfileViewModel>();
}

Navigation using MvvmCross provides a nice abstraction away from the UI layer. It can also be customised to display master-detail, tabbed and other page types.

Getting Started with Xamarin.Forms and Effects

Previous posts in this sequence:
Getting Started with Xamarin.Forms and Multi-Targeting in Visual Studio
Getting Started with Xamarin.Forms and SDK Versions
Getting Started with Xamarin.Forms with MvvmCross
Getting Started with Xamarin.Forms and Authenticating with ADAL
Getting Started with Xamarin.Forms, Refactoring MvvmCross and Services

At some point in building a cross platform application using Xamarin.Forms you’ll need to build out some platform specific features. There are a couple of ways to do this, depending on what you want to achieve. One of those ways is to use an Effect. In this example we’re going to create an Effect that can be used to add a tooltip to any element. For the purposes of this exercise we’re going to assume that this only makes sense to add on UWP where the application can be used on a desktop where the user has a mouse and keyboard attached.

An Effect has two parts:

- A platform agnostic class which will contain any properties that the Effect needs to expose in XAML. This is the name of the element that will appear in XAML. In this case the class will be called TooltipEffect and inherits from RoutingEffect

- A platform specific class which provides the platform specific implementation. In this case this class will be called TooltipPlatformEffect and inherits from PlatformEffect. Note that as this is platform specific, it needs to reside in the platform specific folder

As an Effect is a UI component, it should be added to the UI project, which should now look something like:

image

A couple of things to note here:

- There are folders for Converters, Effects and Renderers – I’ve added these as they are common elements that you’ll be adding to your UI project

- I’ve moved MainPage into a folder called Pages

- In a lot of cases I’ll have another folder called Controls, which will contain any custom or user controls I build.

- The TooltipEffect class sits in the Effects folder (platform agnostic)

- The TooltipEffect.Platform file, which contains the TooltipPlatformEffect class, sits in the Uap platform specific folder

Now, let’s look at the implementation of the effect. First, we’ll start with the TooltipEffect:

public class TooltipEffect : RoutingEffect
{
     public TooltipEffect() : base("StrataPark.TooltipEffect")
     {
     }

    public string Tooltip { get; set; }
}

This class exposes a Tooltip string property which will be used to specify the tooltip text in XAML. In the call to the base constructor it passes in a unique identifier for the Effect. This is important to note because it needs to align with the identifier used by the platform specific implementation. Speaking of which, here’s the TooltipPlatformEffect:

[assembly: ResolutionGroupName("StrataPark")]
[assembly: ExportEffect(typeof(TooltipPlatformEffect), nameof(TooltipEffect))]

namespace StrataPark.UI.Effects
{
     [Preserve]
     public class TooltipPlatformEffect : PlatformEffect
     {
         protected override void OnAttached()
         {
             var view = Control ?? Container;

            var effect = Element.Effects.OfType<TooltipEffect>().FirstOrDefault();
             if (!string.IsNullOrWhiteSpace(effect?.Tooltip) && view != null)
             {
                 var toolTip = new ToolTip
                 {
                     Content = effect?.Tooltip
                 };
                 ToolTipService.SetToolTip(view, toolTip);
             }
         }

        protected override void OnDetached()
         {
         }
     }
}

The most important part of this code are the assembly level attributes that register both the namespace (i.e. the StrataPark prefix) and the element identifier (nameof(TooltipEffect) gives the second part of the identifier, “ToolTipEffect”). If the combination of these attributes don’t yield the same identifier set in the platform agnostic Effect, the platform specific implementation won’t be loaded at runtime.

You can now use this Effect in XAML as follows

<Button Text="Authenticate" Command="{Binding AuthenticateCommand}">
     <Button.Effects>
         <effects:TooltipEffect Tooltip="Welcome tooltip"/>
    </Button.Effects>
</Button>

One last note – when adding folders to your project, you should keep an eye on the changes that take place in your csproj. When you add/remove files and folders, occasionally Visual Studio will add unnecessary items to the csproj. Remember that by default files and folders will be include in the new csproj format. So for example, the following xml is not required, and should be removed, prior to checking your code in:

<ItemGroup>
   <Folder Include="Converters\" />
   <Folder Include="Renderers\" />
</ItemGroup>

As you’ve seen, Effects are one way to add platform specific UI logic to your application. An alternative, is to use Renderers but that’s a topic for another post.