Tag Archives: Plug-ins

Serialise and De-Serialise Helpers for ObservableCollection

I recently came across a need to serialise and de-serialise an ObservableCollection from an MVVMCross application. To achieve this, I created a couple of helper methods which I’d like to share.

Both use the MVVM Cross File plug-in.

Serialise

        public static void Serialise<T>(ObservableCollection<T> collection, string fileName)
        {
            var file = Mvx.Resolve<IMvxFileStore>();
            var fileData = file.OpenWrite(fileName);

            DataContractSerializer serializer = new
                        DataContractSerializer(typeof(ObservableCollection<T>));
            serializer.WriteObject(fileData, collection);
            fileData.Flush();
        }

De-serialise

        public static ObservableCollection<T> DeSerialise<T>(string fileName)
        {
            var file = Mvx.Resolve<IMvxFileStore>();
            if (!file.Exists(fileName))
                return null;

            var fileData = file.OpenRead(fileName);
            if (!fileData.CanRead || fileData.Length == 0)
                return null;

            DataContractSerializer serializer = new
                        DataContractSerializer(typeof(ObservableCollection<T>));

            ObservableCollection<T> data = (ObservableCollection<T>)serializer.ReadObject(fileData);
            return data;
        }

The Serialise method can be wrapped in an extension method, too:

        public static void Serialise<T>(this ObservableCollection<T> collection, string fileName)
        {
            Helpers.SerialiseHelper.Serialise(collection, fileName);
        }

Obviously, the `DeSerialise` cannot, as it would change the object that you are extending.

MVVM Cross – Creating a New Plug-in

This is quite a straightforward process, and well documented in several places – including here and here; and the sample that I used to create mine (and this tutorial) is here. However, I couldn’t find a step-by-step tutorial in a single place. So this is pretty much for my future self.

Disclaimer(s)

This only applies to Windows Store and Windows Phone. Although I believe the same process applies to iOS and Android.

The plug-in that I’m creating here will create a secondary tile on Windows Phone / Windows Store. However, this only covers the phone part, and doesn’t actually cover tile creation.

Create a Project

The project that I’m dealing with is a re-write of this application, using C# and MVVM Cross.

Obviously, your structure may be different, but the important thing is the Plugins folder at this stage; create a new portable project.

plugin1

Next, add the MVVMCross libraries:

plugin2

Interface and Plugin Loader

The portable class library above needs two files. Start with creating an interface:

    public interface ITile
    {
        Task<bool> CreateTile(string title);
    }

And next, the plug-in loader:

    public class PluginLoader : IMvxPluginLoader
    {
        public static readonly PluginLoader Instance = new PluginLoader();

        public void EnsureLoaded()
        {
            var manager = Mvx.Resolve<IMvxPluginManager>();
            manager.EnsurePlatformAdaptionLoaded<PluginLoader>();
        }
    }
}

Obviously, the next stage depends on your specific implementation. Mine depends entirely on the platform, so that’s all I need to do in the portable library.

Windows Phone

Create a new library project:

plugin3

plugin4

As before, you need to add the MVVM Cross Libraries, and a reference to the portable class above:

plugin5

The next stage is to implement your plug-in logic for the destination platform; in my case, this is logic to add a tile to Windows Phone:

    public class TilePlugin : ITile
    {
        public async Task<bool> CreateTile(string title)
        {
            // Create Tile code
        }
    }

Finally, just implement IMvxPlugin like this:

    public class Plugin : IMvxPlugin
    {
        public void Load()
        {
            Mvx.RegisterSingleton<ITile>(new TilePlugin());
        }
    }

Using the plug-in – the View Model

So, to all intents and purposes, the plug-in is now written (admittedly it only exists for Windows Phone, but that’s beside the point).

Next, it needs to be used; the first thing is to reference it.

plugin6

Here’s my logic to actually use the plug-in inside the view model:

    class SetupNewMailViewModel : BaseViewModel
    {
	. . . 
	
	        private void AddTile()
	        {
	            var tile = Mvx.Resolve<ITile>();
	            tile.CreateTile(MailHeading);
	        }
	    }
	

Using the plugin – Platform Specific

In the relevant project, a reference is needed:

plugin7

The only thing left to do for the platform is to add the bootstrap code:

public class TilePluginBootstrap : MvxPluginBootstrapAction<Tile.Plugin.PluginLoader> {    }

`MvxPluginBootstrapAction` signifies that the call to `MvxSetup` will call the BootstrapRunner for this plugin. Or, to put it another way, this magically makes MVVMCross aware of your new plugin for each platform.

Notes on Deployment

Above, I’ve basically manually added the reference to the correct project. This works fine when I’m working locally, but for an actual distributed plug-in, it’s NuGet that handles this.

MVVM Cross Visibility Plugin

A quick forward: there is nothing in this post that isn’t already published here: https://github.com/MvvmCross/MvvmCross/wiki/Value-Converters#the-mvx-visibility-valueconverters.

In this post I referred to a BooleanToVisibilityConverter Windows Store implementation for MVVM Cross. The approach that I outlined in the post will definitely work; however, it will mean re-writing the converter for each platform. So, this post corrects that error.

It was then pointed out to me by a work colleague that there is a Visibility plug-in for MVVM Cross. I wasn’t aware of this, but now that I am, here’s how it works.

Add a reference from NuGet in the front end:

refnuget

Once you’ve added that, here is the revised and simplified code for the converter:

using Cirrious.CrossCore.WindowsStore.Converters;
using Cirrious.MvvmCross.Plugins.Visibility;


namespace MyGame.Converters
{
    public class BooleanToVisibilityConverter : MvxNativeValueConverter<MvxVisibilityValueConverter> { }
}

You will need a wrapper like this for each platform, but at least you’re not re-writing the visibility converter again and again.