New BuildIt Release for NetStandard 2.0 (General, States and Forms)

New BuildIt Release for NetStandard 2.0 (General, States and Forms)

A new release of the following libraries is available via NuGet (v1.1.0.134):

BuildIt.General

BuildIt.States

BuildIt.Forms

Whilst not much has changed in terms of features, behind the scenes there was quite a significant change as we adjusted the solution/project structure, and thus the nuget package structure. We took advantage of the ability to multi-target which meant we no longer have to have separate projects/libraries in order to support platform specific features. BuildIt.General, which used to have a UWP specific library, is now a single libary. Same goes for BuildIt.States. BuildIt.Forms has two libraries, down from the 5 that it used to have.

Additionally we also added direct support for netstandard 2.0. As part of the build process, each library is compiled for netstandard 1.0, netstandard 2.0 and then any platforms that have additional features.

In this release we’ve released multiple packages with the same version number, even though there is an interdependency between them (Forms –> States –> General).

Please reach out and let me know if you see any issues in this release with any of these libraries. We’ll be working to release updates to the other BuildIt libraries over the coming weeks.

Building Applications for Platform X

Building Applications for Platform X

As we get started with a new year it’s time to pause and think about how the app development ecosystem has evolved, what technologies continue or are emerging, and look at the decision matrix that will define what technology your next application is developed in. I’m going to treat this post as a bit of an intro to some of the technologies that I think are worth further investigation.

I think the easiest way to do this is to walk the spectrum from web apps through to native platform apps:

Web Apps

When we talk about web apps, there is a natural assumption that these will be responsive web sites that will work across a wide range of devices and browsers. However, they can be divided further into what I would consider traditional web sites and single page applications. Whilst this division can be blurred, for example when you host an Angular application within a .NET core application, the point is that there is a difference in the mindset of the developers building the web app.

Of course, this section includes the obvious ASP.NET Core, React and Angular. Whilst ASP.NET is still a valid choice, I specifically left it out of the list as I think most new projects will favour ASP.NET Core unless there is an impediment that requires full ASP.NET.

Progressive Web Applications allow web developers to extend their applications to leverage more device capabilities. This is a particularly hot area of development for most platforms as this is seen as one of the best long term solution for minimising mobile development fatigue.

Hybrid

Next in the progression are hybrid applications which combine web technologies with a platform specific deployment package – this sounds a bit cryptic but that’s because there are a couple of different models for this.

Firstly there’s the Cordova/PhoneGap model where the application is defined using html, css, javascript, and wrapped in a native platform deployment package. The deployment step is required in order for most stores to accept applications. The important thing here is that the layout and logic for the application is packaged with the application and that the platform web rendering engine is used to display the application.

The second model is much more interesting and is one that’s being used by React Native and Native Script where the logic and layout is defined in javascript, css and a form of HTML. The HTML actually defines native elements that will be rendered in the correct location.

Cross Platform

Before we get to native platform tools and technologies, we’ll stop in on a long time friend, Xamarin. As with the previous sections there are again two options with Xamarin: traditional Xamarin, and Xamarin Forms. With the traditional Xamarin approach the developer is much closer to the metal and has a higher degree of control. However, the Xamarin Forms option allows for user interfaces to be rapidly developed once, and then feedback/issues are resolved on a platform by platform basis.

Native Platform

Lastly, we have the Native platform options for developers:

Android

Java, C++ with Eclipse, Android Studio

iOS

Objective C, Switft, Interface Builder (now part of XCode)

UWP

C#, XAML, Visual Studio (or Visual Studio for Mac)

As this is hopefully one in a sequence of posts on the topic of framework selection, I’d love some feedback on what technology you think will be important to you and those you work with – comments are off but hit me up on twitter @thenickrandolph if you have thoughts on this.

Making MvvmCross with Xamarin Forms Friction Free

Making MvvmCross with Xamarin Forms Friction Free

My last two posts (part 1 and part 2) outlined all the steps necessary to get a new Xamarin Forms with MvvmCross project setup. What I thought was going to be a simple post ended up being much longer due to all the unnecessary steps to setup both Xamarin Forms and MvvmCross. I’ve recently been contributing a little to MvvmCross and one of my concerns with it is that there are just way to many things that you need to get right in order to get it to work nicely with Xamarin Forms. If you don’t follow one of the introductory posts, such as the one provided by Martjin van Dijk, you’ll probably start hacking around with the numerous extension points in order to get it to work. I spent time over the last day seeing if I could reduce this initial friction to getting started.

When you adopt a framework, or any library for that matter, you do so to reduce the need to reinvent the wheel – there’s no point in recreating, or creating something new, if there are existing solutions available. However, I’m of the opinion that you should be able to determine how much the framework influences the way that your code is structured. You should only have to modify your code if the framework offers a clear advantage. If we do a quick review of some of the changes required to take advantage of MvvmCross in our Xamarin Forms project you’ll see that quite a few of these are artificial requirements, mandated by the current MvvmCross implementation, rather than for any specific need. Here are just a couple:

  • App needs to inherit from MvxFormsApplication – this doesn’t add anything other than a couple of events, so unless you want to use those events, this is unnecessary
  • All pages need to inherit from the Mvx equivalent (eg MvxContentPage instead of ContentPage) – the Mvx equivalent expose a ViewModel property which can be useful but is not required in order to take advantages of data binding to the corresponding ViewModel since all Forms elements have a BindingContext that’s used for this purpose. The actual requirement here is for views/pages to implement IMvxView but unless you need the ViewModel property this shouldn’t be a requirement.
  • You need to create a class that inherits from MvxApplication which can do things like register services but most importantly defines what the starting ViewModel is going to be. This is kind of unnecessary if the only thing that it’s doing is defining the starting ViewModel, although I do understand the desire to have the starting ViewModel defined somewhere that is independent of the head projects.
  • All ViewModels need to inherit from MvxViewModel or implement IMvxViewModel – again this is somewhat unnecessary since ViewModels should just be a regular class. Now I do agree that in most cases your ViewModel is likely to implement INotifyPropertyChanged, so this additional requirements isn’t a massive addition but needless to say it shouldn’t be a requirement.

Ok, so after a bit of experimenting without modifying MvvmCross or MvvmCross.Forms (ie I’m just using the NuGet packages) what I came up with is BuildIt.MvvmCross.Forms (currently in prerelease!) which is a NuGet package which adds a couple of helper classes to get you going just that bit quicker. Here are the steps to get started using BuildIt.MvvmCross.Forms:

Start by following the steps outlined in part 1 – this will give you a Xamarin Forms project that’s completely up to date. I’ll call this project LowFriction

Next, follow the early steps in part 2 to add an additional project for your ViewModels, LowFriction.Core, and subsequently add references to MvvmCross (to all projects) and MvvmCross.Forms (to all projects except the Core project).

Add a reference to the BuildIt.MvvmCross.Forms NuGet package to all projects except the Core project. A primary requirement here is that the Core project should not have a reference to the view technology, which in this case is Xamarin Forms – if you find yourself adding a reference (directly or otherwise) to Xamarin Forms to your Core project, you’ve done something wrong and you should rethink the decisions that led you to that point.

You still need to change App.xaml to inherit from MvxFormsApplication – I couldn’t find a work around this requirements

Your pages do not need to change to implement iMvxView – MainPage inherits from ContentPage

In your Core project you will need to create ViewModels that map to your pages, and they need to implement iMvxViewModel – again I couldn’t find a work around for this requirement. MainViewModel inherits from MvxViewModel.

In your Core project you do not  need to create a class that inherits from MvxApplication – we’ll come to this later but essentially BuildIt.MvvmCross.Forms has class called TypedMvxApplication whose type parameter is the starting ViewModel. If you do want to extend the MvxApplication you can still create your own application but I would recommend using TypedMvxApplication as a starting point

UWP

In App.xaml.cs replace

Xamarin.Forms.Forms.Init(e);

with

var setup = new SetupFromViewModel<MainViewModel, LowFriction.App>(rootFrame, e);
setup.Initialize();

You can see here that the SetupFromViewModel class accepts the starting ViewModel as a parameter. If you’d prefer to define the starting ViewModel in the Core project I recommend defining a class that inherits from TypedMvxApplication, specify the starting ViewModel as the type parameter, and then use the SetupFromApplication class in App.xaml.cs.

Change MainPage to inherit from BuildIt.MvvmCross.Forms.UWP.MvxFormsWindowsPage (I also updated the layout of MainPage to show some data coming from databinding from the ViewModel, similar to what I did in my previous post)

Change the MainPage constructor to

public MainPage()
{
     this.InitializeComponent();


    MvxLoadApplication();
}

Android

Change MainActivity to inherit from CustomMvxFormsAppCompatActivity<SetupFromViewModel<MainViewModel, LowFrictionApp>, MainViewModel>

Comment out the Xamarin Forms init code:

//global::Xamarin.Forms.Forms.Init(this, bundle);
//LoadApplication(new App());

iOS

Change AppDelegate to inherit from CustomMvxFormsApplicationDelegate

Change FinishedLaunching

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     Window = new UIWindow(UIScreen.MainScreen.Bounds);


    var setup = new SetupFromViewModel<MainViewModel, App>(this, Window);
     setup.Initialize();


    MvxLoadApplication();


    Window.MakeKeyAndVisible();


    //global::Xamarin.Forms.Forms.Init();
     //LoadApplication(new App());


    return base.FinishedLaunching(app, options);
}

And we’re done! Build and run on each platform and you should be good to go.

As you can see there are significantly fewer steps involved in getting started, and few additional classes to be created. I do note that there is still room for improvement and I feel that as frameworks go MvvmCross has been developed with extensibility in mind – which is why I was able to streamline the getting started experience so much.

Getting Started: MvvmCross with Xamarin Forms (Part 2)

Getting Started: MvvmCross with Xamarin Forms (Part 2)

In my previous post I covered the first part of this post on Getting Started with MvvmCross and Xamarin Forms where I covered the initial steps in getting a new Xamarin Forms project started. In this post I’m going to continue on and show how you can configure a Xamarin Forms solution to make use of MvvmCross.

Before I get started with MvvmCross I’m going to add a new project which will contain all my ViewModels. Whilst not entirely necessary, particularly with Xamarin Forms where the views/pages are in a .NET Standard library, it’s good practice to completely separate your ViewModels away from the views/pages to avoid any accidental interdependencies forming. I’ll add a new project based on the .NET Standard class library template.

image_thumb11[1]

For this library I’m going to adjust the .NET Standard version back to 1.0 – I prefer to start with a low .NET Standard version and increase it only when I need to take advantage of features in the higher versions. This ensures that the library can be referenced by the widest set of targets platforms.

image_thumb11

I’ll add a reference to the new project to each of the other projects in the solution.

image_thumb31

The next step is to add a reference to the MvvmCross NuGet package. Currently MvvmCross is still distributed as a set of Portable Class Libraries and if we attempt to add the NuGet package to either our MvvmcrossGettingStarted or MvvmcrossGettingStarted.Core projects, we’ll get an error as they’re both .NET Standard library. What’s annoying about this is that the MvvmCross PCLs are fully compatible with .NET Standard, meaning that it should be possible to add a reference to them. Unfortunately Visual Studio isn’t clever enough to be able to resolve this, and as such we need to adjust the csproj files for both projects before attempting to add a reference to MvvmCross.

Add the following line into the first PropertyGroup of the csproj files for both MvvmcrossGettingStarted or MvvmcrossGettingStarted.Core projects. One saving grace is that it’s now easy in Visual Studio to edit a csproj by right-clicking on the project and selecting “Edit <project name>.csproj”.

<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wpa81</PackageTargetFallback>

Eg.

image_thumb23

Next we can go ahead and add a reference to MvvmCross to all our projects. Right-click on the solution node in Solution Explorer and select Manage NuGet Packages for Solution, and then search for mvvmcross. Select the most recent stable version of MvvmCross (this image is a little old as the version is at 5.6.3 at time of writing this)

image_thumb9

In addition to the main MvvmCross package, we also want to add in the Xamarin Forms support library, MvvmCross.Forms. Note that we do not add this to the MvvmcrossGettingStarted.Core project – this is the separation of concerns we setup at the beginning of this post to ensure there is no dependencies on the viewing technology within our ViewModels.

image_thumb21

Now that we have added the references to MvvmCross there are a bunch of small changes we need to apply to our application in order to get it all up and running. We’ll start in the MvvmcrossGettingStarted.Core project where we need to create two classes.

The first class we’ll create inherits from MvxApplication and is used to setup the application within the ViewModel world. MvvmCross has an opinionated navigation model whereby navigation is defined at a ViewModel level, and simply implemented at a View level. As such the MvxApplication class, in this case GettingStartedApplication, defines the first ViewModel for the application.

public class GettingStartedApplication : MvxApplication
{
     public override void Initialize()
     {
         RegisterNavigationServiceAppStart<MainViewModel>();
     }
}

The second class is the ViewModel that matches the first view or page of the application. MainPage was created back when we created the Xamarin Forms application, so we’ll create a class called MainViewModel. Whilst you can override the default view to viewmodel mapping in MvvmCross, it’s preconfigured to align views and viewmodels based on a naming convention. I typically stick with XXXViewModel and XXXPage but XXXView is also supported out of the box.

In this case MainViewModel exposes a simple property that we’ll data bind to later to show that the Page and ViewModel have been glued together correctly.

public class MainViewModel: MvxViewModel
{
     public string WelcomeText => “Welcome to my data bound Xamarin Forms + MvvmCross application!”;
}

Now we’ll switch over to the MvvmcrossGettingStarted project and make some changes to both the App and MainPage classes.

In the App.xaml, we need to change the root element to reference MvxFormsApplication

<?xml version=”1.0″ encoding=”utf-8″ ?>
<mvx:MvxFormsApplication 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=”MvvmcrossGettingStarted.App”>
     <Application.Resources>
     </Application.Resources>
</mvx:MvxFormsApplication>

And in App.xaml.cs, remove the inheritance – the Microsoft templates insist on including the inheritance in both the xaml and xaml.cs files which is quite unnecessary and should be removed.

public partial class App
{
     public App()
     {
         InitializeComponent();
     }
}

We need to make a similar change to MainPage.xaml, changing the root element to MvxContentPage. We’ll also change the Label to use data binding to return the WelcomeText property from the MainViewModel.

<?xml version=”1.0″ encoding=”utf-8″ ?>
<mvx:MvxContentPage 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=”MvvmcrossGettingStarted.MainPage”>
     <Label Text=”{Binding WelcomeText}”
            VerticalOptions=”Center”
            HorizontalOptions=”Center” />
</mvx:MvxContentPage>

Again, remove the inheritance specified in MainPage.xaml.cs

public partial class MainPage
{
     public MainPage()
     {
         InitializeComponent();
     }
}

The next step involves adding a Setup class to each of the head projects, and then creating an instance of the Setup class to invoke MvvmCross when the application starts up.

UWP

The UWP Setup inherits from MvxFormsWindowsSetup and unlike the Android and iOS Setup classes, the UWP Setup needs to override the default log behaviour by setting the log provider type to None and then creating an instance of the EmptyVoidLogProvider  (the implementation of this is coming up soon) – this should be fixed in a future MvvmCross version.

public class Setup : MvxFormsWindowsSetup
{
     public Setup(Frame rootFrame, LaunchActivatedEventArgs e) : base(rootFrame, e)
     {
     }


    protected override MvxLogProviderType GetDefaultLogProviderType() => MvxLogProviderType.None;


    protected override IMvxLogProvider CreateLogProvider() => new EmptyVoidLogProvider();


    protected override IEnumerable<Assembly> GetViewAssemblies()
     {
         return new List<Assembly>(base.GetViewAssemblies().Union(new[] { typeof(MvvmcrossGettingStarted.App).GetTypeInfo().Assembly }));
     }


    protected override MvxFormsApplication CreateFormsApplication() => new MvvmcrossGettingStarted.App();


    protected override IMvxApplication CreateApp() => new Core.GettingStartedApplication();
}

Now in App.xaml.cs we need to replace

Xamarin.Forms.Forms.Init(e);

with

var setup = new Setup(rootFrame, e);
setup.Initialize();

And in Main.xaml.cs replace

LoadApplication(new MvvmcrossGettingStarted.App());

with

var start = Mvx.Resolve<IMvxAppStart>();
start.Start();


var presenter = Mvx.Resolve<IMvxFormsViewPresenter>() as MvxFormsUwpViewPresenter;
LoadApplication(presenter.FormsApplication);

Finally, we need to add the EmptyVoidLogProvider

public class EmptyVoidLogProvider : IMvxLogProvider
{
     private readonly EmptyVoidLog voidLog;


    public EmptyVoidLogProvider()
     {
         voidLog = new EmptyVoidLog();
     }


    public IMvxLog GetLogFor<T>()
     {
         return voidLog;
     }


    public IMvxLog GetLogFor(string name)
     {
         return voidLog;
     }


    public IDisposable OpenNestedContext(string message)
     {
         throw new NotImplementedException();
     }


    public IDisposable OpenMappedContext(string key, string value)
     {
         throw new NotImplementedException();
     }


    public class EmptyVoidLog : IMvxLog
     {
         public bool Log(MvxLogLevel logLevel, Func<string> messageFunc, Exception exception = null, params object[] formatParameters)
         {
             return true;
         }
     }
}

Now when we build and run the UWP project we can see that the MainPage is shown and is data bound to the MainViewModel.

image

iOS

The iOS Setup is the simplest out of the three platforms.

public class Setup : MvxFormsIosSetup
{
     public Setup(IMvxApplicationDelegate applicationDelegate, UIWindow window)
         : base(applicationDelegate, window)
     {
     }


    protected override IEnumerable<Assembly> GetViewAssemblies()
     {
         return new List<Assembly>(base.GetViewAssemblies().Union(new[] { typeof(MvvmcrossGettingStarted.App).GetTypeInfo().Assembly }));
     }


    protected override MvxFormsApplication CreateFormsApplication() => new MvvmcrossGettingStarted.App();


    protected override IMvxApplication CreateApp() => new Core.GettingStartedApplication();
}

In AppDelegate we need to change the inheritance from  global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate to MvxFormsApplicationDelegate and change the FinishedLaunching method as follows:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     Window = new UIWindow(UIScreen.MainScreen.Bounds);


    var setup = new Setup(this, Window);
     setup.Initialize();


    var startup = Mvx.Resolve<IMvxAppStart>();
     startup.Start();


    LoadApplication(setup.FormsApplication);


    Window.MakeKeyAndVisible();


    return base.FinishedLaunching(app, options);
}

Now we’re good to build and run the iOS project

image

Android

Lastly, add Setup to the Android project. Note this is slightly different from the iOS and UWP projects in that the GetViewAssemblies method excludes the assembly for the Android head project. This is to avoid the MainActivity being added as a view, that based on our naming convention would match with MainViewModel giving a duplicate when attempting to resolve the View that should be rendered.

public class Setup : MvxFormsAndroidSetup
{
     public Setup(Context applicationContext) : base(applicationContext)
     {
     }


    protected override IEnumerable<Assembly> GetViewAssemblies()
     {
         return new List<Assembly>(base.GetViewAssemblies()
             .Union(new[] { typeof(MvvmcrossGettingStarted.App).GetTypeInfo().Assembly })
             .Except(new[] {this.GetType().Assembly})
             );
     }


    protected override MvxFormsApplication CreateFormsApplication() => new MvvmcrossGettingStarted.App();


    protected override IMvxApplication CreateApp() => new Core.GettingStartedApplication();
}

The MainActivity needs to be updated to change its inheritance from global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity to MvxFormsAppCompatActivity<MainViewModel>. And the OnCreate needs to be updated to

[Activity(Label = “MvvmcrossGettingStarted”, Icon = “@drawable/icon”, Theme = “@style/MainTheme”, MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : MvxFormsAppCompatActivity<MainViewModel>
//global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
     protected override void OnCreate(Bundle bundle)
     {
         TabLayoutResource = Resource.Layout.Tabbar;
         ToolbarResource = Resource.Layout.Toolbar;


        base.OnCreate(bundle);


        var startup = Mvx.Resolve<IMvxAppStart>();
         startup.Start();
         InitializeForms(bundle);


     }
}

Finally the last platform, Android, is good to build and run. Note however that Android has a tendency to be a pain and that after setting everything up correctly you may still run into issues building, deploying and running. Before you waste hours looking at your code to see what you’ve done wrong, make the assumption that the tools are crap – delete both bin and obj folders from the Android head project, and uninstall the application from the device/emulator (assuming it has already been installed). Try building and running again – if this still fails, then you may indeed have something wrong with your code!

image

Getting Started: MvvmCross with Xamarin Forms

Getting Started: MvvmCross with Xamarin Forms

Over the past 6-12 months we’ve seen dramatic changes in Xamarin Forms and the support within Visual Studio. The most recent update, which I covered in my previous post, included a number of new features for cross platform developers. However, despite these updates, getting started with cross platform development is still quite complex. In this post I wanted to take the opportunity to reiterate how to start a new Xamarin Forms project. From there I’ll cover adding in MvvmCross and discuss the importance of having a framework that will make development that much easier (for the record MvvmCross isn’t the only option, there are plenty of great alternatives such as Prism and FreshMvvm).

Part 1: Getting Started with Xamarin Forms

Before getting started, make sure you’ve run the Visual Studio Installer and have upgraded to the latest stable release of Visual Studio. The team at Microsoft have been putting a lot of focus on stability and performance, so upgrading to the latest version does help (still not perfect but a marked improvement over this time last year!). Upgrading Visual Studio continually can be a bit of a pain, especially since Microsoft haven’t quite worked out how to automatically download updates in the background for VS – meaning that you have to stop whatever you’re doing whilst the updates download and then install. Recommendation is to run the installer periodically at the end of your day, or when you’re heading to a long meeting; hopefully the installation is complete by the time you return.

Now that you’re all up to date, let’s create a new solution by selecting the Cross-Platform App (Xamarin Forms) template from the New Project dialog. Note that if you don’t see this template, you may have to adjust the workloads you selected in the VS Installer so that you have all the cross-platform development components selected.

image

After clicking OK you should be presented with a second dialog that allows you to specify parameters for how your cross platform project should be setup. As you can see from the image, I recommend always selecting all three platforms (even if you’re only planning on targeting one or two of them initially); In this case we’re going with Xamarin.Forms with a simple Blank App; The last option I’m particularly passionate about – do NOT select Shared Project – for the good of your project, the team and general good programming practice, please select the .NET Standard option for Code Sharing Strategy. At time of writing the .NET Standard option is only available in the preview build of Visual Studio; the stable build uses a Portable Class Library, which is still preferable over using a Shared Project.

image

This time clicking OK will create a new solution.

Unexpected Error when Creating Solution

Unfortunately, at time of writing this post there is also a bug in the current cross platform template that results in the following error:

image

If you see this error, a quick Google will yield the following bugzilla issue (https://bugzilla.xamarin.com/show_bug.cgi?id=60995) which describes the issue, along with how to fix it yourself – you just need to edit the Android csproj file and remove the ” from around the TargetFrameworkVersion ie:

replace:

<TargetFrameworkVersion>”v8.0″</TargetFrameworkVersion>

with

<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>

After fixing up the csproj file you’ll need to add the existing projects into the solution file.

Assuming you didn’t run into any issues creating the solution, or you were able to fix up the Android csproj file, you should be able to build and run each of the head projects:

UWP

image

Note: When building the UWP project I was seeing a build warning stating “warning APPX0108: The certificate specified has expired.” which I thought was a bit odd since I had just created the project and normally the certificate that is used for debug builds is created alongside the new project. Double-clicking the package.appxmanifest and switching to the Packaging tab I see that the Publisher display name isn’t set correctly – I’m guessing at this point that the cross platform template contains an existing certificate, instead of creating one each time. You can easily fix this by changing the publisher display name, clicking Choose Certificate and then from the dropdown select “Create test certificate”.

image

Now when you build the project you won’t see this warning – I’m guessing this is also a bug in the preview version of the cross platform template.

Android

image

For Android I’m using the Google Android Emulator that can now be installed using the Visual Studio Installer. This is significantly better than it used to be, and the images are much more recent than those for the Visual Studio Android Emulator which has been deprecated now.

iOS

image

For iOS, as I’m working from a Windows laptop, I use the Remote Simulator which works really well and means I don’t need to continually VNC to my MacMini or have to deploy to a real device.

Again there was an issue with the iOS template in that the MinimumOSVersion was set to “11.2” instead of just 11.2 in the Info.plist file.

<key>MinimumOSVersion</key>
<string>11.2</string>

Correcting the MinimumOSVersion will allow your application to run on a device or emulator.

Now that we’ve validated that all the platforms run, it’s time to make sure they’re setup correctly ready for us to add in Mvvmcross and to set the foundation of our application. Android and iOS should be setup correctly, although you may want to double-check to make sure Android is set to use the latest platform version (see Application tab of the Android project properties); UWP defaults to using the Fall Creators Update (FCU) as the minimum version, which is way to recent for applications wanting to target the widest set of customers. Our preferences is to set this back to the November Update

image

Note however, that this does preclude your application from using .NET Standard 2.0 libraries, as these are not compatible with UWP projects prior to the FCU. Unfortunately the .NET Standard library that holds the Xamarin Forms views for the solution is set to .NET Standard 2.0 by default. This is completely unnecessary, so it can be reduced back to 1.4 (or below, depending on your preferences)

image

Next, we want to make sure we’re using the latest NuGet packages – right-click on the solution node in Solution Explorer and select Manage NuGet Packages for Solution

image

After upgrading all the NuGet packages, double-check to make sure all platforms build and run. Now’s a great time to check your solution in to your repository of choice (Note: make sure you check in the pfx file that is part of the UWP solution. You’ll probably have to manually add this file to your repository as most repositories ignore pfx files by default).

Update: Part 2 is now available.

Styling the MediaPlayerElement and MediaTransportControls in a Universal Windows Platform (UWP) Application

Styling the MediaPlayerElement and MediaTransportControls in a Universal Windows Platform (UWP) Application

In my previous post, Building Media Applications for the Universal Windows Platform (UWP) using the MediaPlayerElement, I covered the basics of building a UWP media application using the MediaPlayerElement. Towards the end of the post I showed how you can override some of the built in behaviour but I was yet to show you how you can adjust the visual style of the player or the controls. In this post I’ll do just that, I’ll show you where to find the built in styles and how to start customizing them, including some gotchas that you should be aware of.

Ok, let’s get started by looking for the built in styles. Whilst Microsoft now do a good job of documenting the built in styles online (for example the styles and templates for the MediaTransportControls element is defined at https://msdn.microsoft.com/en-us/library/windows/apps/mt414180.aspx), there is nothing like looking at what ships in the platform. For this we go to generic.xaml, typically located at C:Program Files (x86)Windows Kits10DesignTimeCommonConfigurationNeutralUAP10.0.16299.0Generic – Note that this may vary based on which platform SDK you have installed. Inside generic.xaml I’m going to locate the Style for the MediaPlayerElement:

<Style TargetType=”MediaPlayerElement”>
     <Setter Property=”HorizontalAlignment” Value=”Stretch” />
     <Setter Property=”VerticalAlignment” Value=”Stretch” />
     <Setter Property=”IsTabStop” Value=”False” />
     <Setter Property=”Template”>
         <Setter.Value>
             <ControlTemplate TargetType=”MediaPlayerElement”>
                 <Grid x_Name=”LayoutRoot”>
                     <Border Background=”Transparent” />
                     <Image  x_Name=”PosterImage”
                         Visibility=”Collapsed”
                         Source=”{TemplateBinding PosterSource}”
                         Stretch=”{TemplateBinding Stretch}” />
                     <MediaPlayerPresenter x_Name=”MediaPlayerPresenter”
                         IsFullWindow=”{TemplateBinding IsFullWindow}”
                         Stretch=”{TemplateBinding Stretch}”
                         MediaPlayer=”{TemplateBinding MediaPlayer}” />
                     <ContentPresenter     x_Name=”TransportControlsPresenter”
                         Visibility=”{TemplateBinding AreTransportControlsEnabled}” />
                     <Grid x_Name=”TimedTextSourcePresenter” />
                 </Grid>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
</Style>

As you can see, the Style for the MediaPlayerElement is made up of a few different components:

  • MediaPlayerPresenter – this is where the actual video content will be displayed
  • ContentPresenter – this is where the player controls will be displayed
  • “TimedTextSourcePresenter” – this is where the closed captions will be presented

Let’s make a subtle change here by adding another Grid immediately after the TimedTextSourcePresenter with a semi-transparent Pink colour and a TextBlock to indicate that this is a customized player.

<Page.Resources>
     <Style TargetType=”MediaPlayerElement”>
         <Setter Property=”HorizontalAlignment”
                 Value=”Stretch” />
         <Setter Property=”VerticalAlignment”
                 Value=”Stretch” />
         <Setter Property=”IsTabStop”
                 Value=”False” />
         <Setter Property=”Template”>
             <Setter.Value>
                 <ControlTemplate TargetType=”MediaPlayerElement”>
                     <Grid x_Name=”LayoutRoot”>
                         <Border Background=”Transparent” />
                         <Image  x_Name=”PosterImage”
                                 Visibility=”Collapsed”
                                 Source=”{TemplateBinding PosterSource}”
                                 Stretch=”{TemplateBinding Stretch}” />
                         <MediaPlayerPresenter x_Name=”MediaPlayerPresenter”
                                                 IsFullWindow=”{TemplateBinding IsFullWindow}”
                                                 Stretch=”{TemplateBinding Stretch}”
                                                 MediaPlayer=”{TemplateBinding MediaPlayer}” />
                         <ContentPresenter     x_Name=”TransportControlsPresenter”
                                                 Visibility=”{TemplateBinding AreTransportControlsEnabled}” />
                         <Grid x_Name=”TimedTextSourcePresenter” />
                        <Grid Background=”Pink”
                                 IsHitTestVisible=”False”
                                 Opacity=”0.4″>
                             <TextBlock Foreground=”Black”
                                         Text=”Custom Player” HorizontalAlignment=”Left” VerticalAlignment=”Bottom” Margin=”50,5,5,5″/>
                         </Grid>

                     </Grid>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
<Page.Resources>

You’ll notice that I’ve added this Style into the Resources dictionary for the page and that it’s an implicit style (ie I haven’t assigned it a Key) which means that any MediaPlayerElement on this page will pick up this style. You can of course set this Style either directly on the MediaPlayerElement itself or even define it in an application level resource dictionary.

image

Note also that the IsHitTestVisible attribute is set on the Grid, otherwise it will block user input to the player controls as the grid sits over the top of the other elements within the MediaPlayerElement control template.

If you recall from my previous post I intercepted the behaviour that steps the video back and forward so that I could customize this behaviour. Of course, this means that the step forward/backward icons aren’t accurate, since I’m not longer stepping back by 10seconds and forward by 30seconds. In order to override the icons on these buttons, I need to override the Style for the MediaTransportControls. Again the default Style can be found in generic.xaml – it’s really long, so I’m not going to copy the whole thing in here. Here’s a cut down version of the Style showing the changes to the FontIcon for the SkipBackwardButton and SkipForwardButton.

<Page.Resources>
     <Style TargetType=”MediaTransportControls”>
     …
         <Setter Property=”Template”>
             <Setter.Value>
                 <ControlTemplate TargetType=”MediaTransportControls”>
                     <Grid x_Name=”RootGrid”
                             Background=”Transparent”>
             …   
             <AppBarButton x_Name=’SkipBackwardButton’
                          Style='{StaticResource AppBarButtonStyle}’
                          MediaTransportControlsHelper.DropoutOrder=’5′
                          Visibility=’Collapsed’>
                           <AppBarButton.Icon>
                         
  <!–<FontIcon Glyph=”&#xED3C;” />–>
                            <FontIcon Glyph=”&#xF100;”
                                      FontFamily=”FontAwesome” />

                           </AppBarButton.Icon>
                         </AppBarButton>
                         …
                         <AppBarButton x_Name=’SkipForwardButton’
                          Style='{StaticResource AppBarButtonStyle}’
                          MediaTransportControlsHelper.DropoutOrder=’5′
                          Visibility=’Collapsed’>
                           <AppBarButton.Icon>
                         
  <!–<FontIcon Glyph=”&#xED3D;” />–>
                            <FontIcon Glyph=”&#xF101;”
                                      FontFamily=”FontAwesome” />
                           </AppBarButton.Icon>

                         </AppBarButton>
                     </Grid>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
</Page.Resources>

You might be wondering where I got the new hex code for the FontAwesome font. Rather than go online and having to hunt down hex values for the different characters within a font, if you open Word and go to Insert, Symbol, you can then select the Font and select the character you want. In the lower right corner it states what the Character code is. Remember that you need to make sure the font exists on the computer you’re going to run the application on, so you may want to consider including the font within your application if you pick a non-standard font.

image

Ok, so running the application now, we can see the updated skip backward and skip forward buttons:

image

Unfortunately, here lies a major bug in the implementation of the MediaPlayerElement – if you press the full screen button, you’ll see that the Style for the MediaTransportControls has reverted back to the built in style.

image

This happens because when the video runs in full screen, the MediaTransportControls are being hosted in a separate visual tree to the main part of the application – you can see this if you look at the Live Visual Tree.

image

So, the question is how to handle this? Well the good news is that it’s surprisingly simple. What’s happening is that as the MediaTransportControls are being attached to a different visual tree, they’re not able to resolve the Style defined within the scope of the page. Moving the custom Style for the MediaTransportControls to an application level resource fixes this issue.

<Application
     x_Class=”PlayerSample.App”
     http://schemas.microsoft.com/winfx/2006/xaml/presentation"”>http://schemas.microsoft.com/winfx/2006/xaml/presentation”
     http://schemas.microsoft.com/winfx/2006/xaml"”>http://schemas.microsoft.com/winfx/2006/xaml”
     RequestedTheme=”Light”>
     <Application.Resources>
         <Style TargetType=”MediaTransportControls”>
         …
         </Style>
     </Application.Resources>
</Application>

The documentation online at https://docs.microsoft.com/en-us/windows/uwp/controls-and-patterns/custom-transport-controls indicates that you should use an explicit style – two things a) this doesn’t fix the full screen issue; you must define the Style at an application level regardless of whether you make it an explicit or implicit style and b) you can make the choice yourself whether to use an implcit or explicit style, depending on whether you want multiple different player styles (ie where an explicit style makes sense).

Visual Studio or Blend Exception When Using XAML Designer

Visual Studio or Blend Exception When Using XAML Designer

Today we ran into a nasty issue with the XAML design experience in Visual Studio and/or Blend throwing an exception:

image

Exceptions in the designer a quite often a result of code being run by the designer that is insufficiently protected using try-catch, or has assumptions that some app startup code has run, resulting in an exception that bubbles up and causes the designer to fail. For these exceptions, I recommend checking out the post How to Debug the XAML Designer by Travis Illig, which uses another instance of Visual Studio to debug and hopefully identify the code that isn’t playing nice.

Unfortunately in our case, this didn’t help because Visual Studio (and same in Blend) was failing to resolve an assembly reference.

image

One thing that Travis point out is that there is a ShadowCache folder located at C:UsersyourusernameAppDataLocalMicrosoftVisualStudio15.0_317bf9c1DesignerShadowCache (note that you’ll need to change both “yourusername” to be your username and perhaps even the 15.0…. to reflect the current version of Visual Studio. Change VisualStudio to Blend if you’re using Blend). Within the ShadowCache folder there will be folders created for each application where you use the designer, and then a series of “bin” sub folders that will contain assemblies referenced by your application.

image

The issue we found was that we were referencing a nuget package that includes both a UWP dll as well as a .NET Standard dll. Whilst the UWP dll was being copied into a bin folder, the .NET Standard dll was not. Our fix for getting the designer to work was to copy the .NET standard dll into the same folder as the UWP dll.

Unfortunately whilst this gets the designer to work, it is a sub-optimal experience as it appears that it needs to be done every time Visual Studio is run, or when the designer process is restarted.