Navigation in Windows Phone with complex parameter type using Caliburn.Micro


Hi guys,

Today I’ll describe the way we do navigation on Windows Phone using Caliburn.Micro for one particular case – when we need to pass instance of complex type.

For those who doesn’t know what complex type is, this could be some class which has properties/fields combined of primitive or other complex types:


    public class Customer
    {
        public string FirstName { get; set; }

        public int Age { get; set; }

        public IEnumerable<Order> Orders { get; set; } 
    }

    public class Order
    {
        public int Quantity { get; set; }
    }

The issue with Windows Phone navigation (even when you use Caliburn.Micro) is that it allows to pass primitive types only:


             navigationService.UriFor<CustomerOrders>()
                .WithParam(model => model.Date, DateTime.Now)
                .Navigate();

This is because Windows Phone navigation system uses Uri approach to pass parameters (e.g. CustomersOrders.xaml?Date=25/07/2014)

Fortunately, I’ve found solution to pass complex properties by implementing extension method for Caliburn.Micro INavigationService:


    public static class NavigationServiceExtensions
    {
        public static void Navigate<TNavigationTarget, TArgument>(this INavigationService navigationService, TArgument parameter) 
            where TNavigationTarget : class, IHaveComplexPropertyOfType<TArgument> where TArgument : class
        {
            NavigatedEventHandler eventHandler = null;
            eventHandler = (sender, args) =>
            {
                FrameworkElement view;
                TNavigationTarget target;
                if ((view = args.Content as FrameworkElement) == null ||
                    (target = view.DataContext as TNavigationTarget) == null) return;

                target.Init(parameter);

                navigationService.Navigated -= eventHandler;
            };

            navigationService.Navigated += eventHandler;
            navigationService.UriFor<TNavigationTarget>().Navigate();
        }
    }

Here I subscribe to Navigated event and use Init method of IHaveComplexPropertyOfType to pass complex parameter. This interface looks has the following member:


    public interface IHaveComplexPropertyOfType<T>
    {
        void Init(T propertyValue);
    }

I’m not sure whether there are other implementations for this scenario available, but this is the way we do navigation and I hope this can help you as well.