Creating a Xamarin Forms App Part 6 : View Model First Navigation

  • Part 1 : Introduction
  • Part 2 : Getting Started
  • Part 3 : How to use Xamarin Forms with Visual Studio without the Business Edition
  • Part 4 : Application Resources
  • Part 5 : Dependency Injection
  • Part 6 : View Model First Navigation
  • Part 7 : Unit Testing
  • Part 8 : Consuming a RESTful Web Service
  • Part 9 : Working with Alerts and Dialogs
  • Part 10 : Designing and Developing the User Interface
  • Part 11 : Updating to Xamarin Forms 1.3
  • Part 12 : Extending the User Interface

So far my app isn’t navigating anywhere as it only has one page showing a list of mountain areas. What I want is for the app to navigate to the forecast when you tap on a mountain area in the list. There are generally two approaches to navigation with MVVM, View First and View Model First.

As the names suggest with View first we create the View and then the View Model, and with View Model first we create the View Model and then the View. In both cases the BindingContext of the View needs to be set to the View Model. I will be taking a View Model first approach. There are very good reasons for this.

MVVM done correctly requires that the View Model does not know about the View, or any view for that matter. The application logic should be in your View Model and not in the View. The View is simply a visual representation. If we adhere to these basic principles then View first really does not fit well with MVVM. I have seen various workarounds such as navigating to a view via a key or even worse referencing the View from the View Model. Then there is the issue of passing state. The state, or more commonly the model needs to be passed to the view model. With View first this becomes a challenge. I have seen state packaged in to uri strings or bundled into messages. All this is nonsense because we don’t need to do this at all. Life becomes a whole lot simpler, as does your application, when we take a View Model first approach.

With View Model first View Models collaborate with and navigate to other View Models. Some developers seem to have some misconceptions about MVVM and think that View Models should not communicate with each other directly. This is nonesense. View Models should never directly communicate with Views, but it is completely natural for View Models to collaborate with other View Models. This is particularly true when you have a view model made up other view models or when a view model needs to navigate to another view model. This is a perfectly natural world and is a fundamental part of our application logic.

In WPF View Model first is made very easy for us with the help of Data Templates. View Model types can be mapped to their Views by defining a Data Template for a View Model Type. This works so well it’s almost magical. Unfortunately Xamarin Forms Data Templates cannot be associated with a Data Type therefore we have to find another way to resolve Views from View Models. This is actually quite easy to achieve using a simple dictionary mapping one type to another.

One other issue is the Xamarin Forms Navigation interface, INavigation.

public interface INavigation
{
    Task<Page> PopAsync();
    Task<Page> PopModalAsync();
    Task PopToRootAsync();
    Task PushAsync(Page page);
    Task PushModalAsync(Page page);
}

If we were to consume this interface from our view models we would be violating the MVVM pattern because we would be dealing directly with Page, which is the View. We definitely don’t want to do that. What we want is an interface that works with view models instead.

In this post I am going to show you how we can achieve View Model first Navigation in a simple and elegant way and extend my application to display weather forecasts for each mountain area.

So, let’s get started.

ViewModelBase

Firstly it’s about time I introduced INotifyPropertyChanged. Yes you guessed it; I need ViewModelBase. I am also going to create an interface to represent a view model named IViewModel rather than directly using INotifyPropertyChanged. BindableObject also implements INotifyPropertyChanged, which I definitely don’t want to be working with. This interface also introduces a Title property and a SetState method.

public interface IViewModel : INotifyPropertyChanged
{
    string Title { get; set; }

    void SetState<T>(Action<T> action) where T : class, IViewModel;
}

Title simply allows each view model to have a Title. The SetState method allows us to provide an action that will set the state of the view model when called. This allows us to reuse view models and set their state when navigating. This is an important consideration for mobile devices. ViewModelBase implements this along with some helper methods for calling PropertyChanged. I have placed these in my Core project in the ViewModels folder.

namespace Silkweb.Mobile.Core.ViewModels
{
    public abstract class ViewModelBase : IViewModel
    {
        public string Title { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public void SetState<T>(Action<T> action) where T : class, IViewModel
        {
            action(this as T);
        }

        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (object.Equals(storage, value)) return false;

            storage = value;
            OnPropertyChanged(propertyName);

            return true;
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = PropertyChanged;
            if (eventHandler != null)
            {
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
        {
            var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
            OnPropertyChanged(propertyName);
        }
    }
}

View Factory

As I mentioned earlier we need some way to map view models to view types. And we also need to be able to resolve the view from a given view model. Create an interface called IViewFactory in the Core project within a Factories folder. Add the following to the interface.

namespace Silkweb.Mobile.Core.Factories
{
    public interface IViewFactory
    {
        void Register<TViewModel, TView>() 
            where TViewModel : class, IViewModel 
            where TView : Page;

        Page Resolve<TViewModel>(Action<TViewModel> setStateAction = null) 
            where TViewModel : class, IViewModel;

        Page Resolve<TViewModel>(out TViewModel viewModel, Action<TViewModel> setStateAction = null) 
            where TViewModel : class, IViewModel;

        Page Resolve<TViewModel>(TViewModel viewModel) 
            where TViewModel : class, IViewModel;
    }
}

The Register method allows us to register a view model with a view type. The Resolve methods allow us to resolve a view from either a view model instance or from a view model type. I have also provided an overload to return both the view and the view model instances. In the same folder add the following implementation.

namespace Silkweb.Mobile.Core.Factories
{
    public class ViewFactory : IViewFactory
    {
        private readonly IDictionary<Type, Type> _map = new Dictionary<Type, Type>();
        private readonly IComponentContext _componentContext;

        public ViewFactory(IComponentContext componentContext)
        {
            _componentContext = componentContext;
        }

        public void Register<TViewModel, TView>() 
            where TViewModel : class, IViewModel 
            where TView : Page
        {
            _map[typeof(TViewModel)] = typeof(TView);
        }

        public Page Resolve<TViewModel>(Action<TViewModel> setStateAction = null) where TViewModel : class, IViewModel
        {
            TViewModel viewModel;
            return Resolve<TViewModel>(out viewModel, setStateAction);
        }

        public Page Resolve<TViewModel>(out TViewModel viewModel, Action<TViewModel> setStateAction = null) 
            where TViewModel : class, IViewModel 
        {
            viewModel = _componentContext.Resolve<TViewModel>();

            var viewType = _map[typeof(TViewModel)];
            var view = _componentContext.Resolve(viewType) as Page;

            if (setStateAction != null)
                viewModel.SetState(setStateAction);

            view.BindingContext = viewModel;
            return view;
        }

        public Page Resolve<TViewModel>(TViewModel viewModel) 
            where TViewModel : class, IViewModel 
        {
            var viewType = _map[typeof(TViewModel)];
            var view = _componentContext.Resolve(viewType) as Page;
            view.BindingContext = viewModel;
            return view;
        }
    }
}

Here I am simply using a dictionary for mapping the types. Of particular note is the IComponentContext. This is an Autofac object that allows us to resolve types outside the normal dependency injection path. This is something that is not normally recommended, but in this case we have a factory class that needs to resolve any type of IViewModel and any type of Page. I could have created a Func<> parameter for this but it wouldn’t really have yielded much benefit and would have made things a bit more complex than they need to be. I may refactor this later, but for now it’s fine as it is. Also notice that I am calling SetState in the resolved view model if the setSetAction is set. This allows the view model’s state to be initialised or changed when resolved.

Navigator

Now we need a Navigation interface similar to Xamarin Forms INavigator except it needs to work with IViewModel. Add an INavigator interface under a Services folder in the Core project with the following definition.

namespace Silkweb.Mobile.Core.Services
{
    public interface INavigator
    {
        Task<IViewModel> PopAsync();

        Task<IViewModel> PopModalAsync();

        Task PopToRootAsync();

        Task<TViewModel> PushAsync<TViewModel>(Action<TViewModel> setStateAction = null) 
            where TViewModel : class, IViewModel;

        Task<TViewModel> PushAsync<TViewModel>(TViewModel viewModel) 
            where TViewModel : class, IViewModel;

        Task<TViewModel> PushModalAsync<TViewModel>(Action<TViewModel> setStateAction = null) 
            where TViewModel : class, IViewModel;

        Task<TViewModel> PushModalAsync<TViewModel>(TViewModel viewModel) 
            where TViewModel : class, IViewModel;
    }
}

Notice this exactly mirrors INavigation except Page is replaced with IViewModel. I have also provided an overload of PushAsync that expects the view model to be resolved automatically and sets the state of view model when it gets resolved. Now add the following Navigator class to the Core project services folder.

namespace Silkweb.Mobile.Core.Services
{
    public class Navigator : INavigator
    {
        private readonly Lazy<INavigation> _navigation;
        private readonly IViewFactory _viewFactory;

        public Navigator(Lazy<INavigation> navigation, IViewFactory viewFactory)
        {
            _navigation = navigation;
            _viewFactory = viewFactory;
        }

        private INavigation Navigation
        {
            get { return _navigation.Value; }
        }

        public async Task<IViewModel> PopAsync()
        {
            Page view = await Navigation.PopAsync();
            return view.BindingContext as IViewModel;
        }

        public async Task<IViewModel> PopModalAsync()
        {
            Page view = await Navigation.PopAsync();
            return view.BindingContext as IViewModel;
        }

        public async Task PopToRootAsync()
        {
            await Navigation.PopToRootAsync();
        }

        public async Task<TViewModel> PushAsync<TViewModel>(Action<TViewModel> setStateAction = null) 
            where TViewModel : class, IViewModel
        {
            TViewModel viewModel;
            var view = _viewFactory.Resolve<TViewModel>(out viewModel, setStateAction);
            await Navigation.PushAsync(view);
            return viewModel;
        }

        public async Task<TViewModel> PushAsync<TViewModel>(TViewModel viewModel) 
            where TViewModel : class, IViewModel
        {
            var view = _viewFactory.Resolve(viewModel);
            await Navigation.PushAsync(view);
            return viewModel;
        }

        public async Task<TViewModel> PushModalAsync<TViewModel>(Action<TViewModel> setStateAction = null) 
            where TViewModel : class, IViewModel
        {
            TViewModel viewModel;
            var view = _viewFactory.Resolve<TViewModel>(out viewModel, setStateAction);
            await Navigation.PushModalAsync(view);
            return viewModel;
        }

        public async Task<TViewModel> PushModalAsync<TViewModel>(TViewModel viewModel) 
            where TViewModel : class, IViewModel
        {
            var view = _viewFactory.Resolve(viewModel);
            await Navigation.PushModalAsync(view);
            return viewModel;
        }
    }
}

Here I am simply calling the View Factory to resolve the view and then calling the Xamarin Forms INavigation instance to navigate to the view. Note, the INavigation instance is passed to the constructor as Lazy. This is because it needs to be deferred until we have set the main page of the application to the navigation page.

Bootstrapper

Now we have our ViewFactory and Navigator we need to register them with Autofac. I want to be able to provide a core bootstrapper with all the core services and factories already registered and then just add the application specific registrations. To do this I need to refactor the existing bootstrapper and provide a core Autofac bootstrapper which I can inherit for my applications bootstrapper.

I will put all my registration in a separate Autofac Module. Create a folder in Core called Bootstrapping and add the following AutofacModule class.

namespace Silkweb.Mobile.Core.Bootstrapping
{
    public class AutofacModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            // service registration
            builder.RegisterType<ViewFactory>()
                .As<IViewFactory>()
                .SingleInstance();

            builder.RegisterType<Navigator>()
                .As<INavigator>()
                .SingleInstance();

            // navigation registration
            builder.Register<INavigation>(context => 
                App.Current.MainPage.Navigation
            ).SingleInstance();
        }
    }
}

This simply registers both our ViewFactory and Navigator against their interfaces as singletons. Notice I am also registering INavigation using a delegate registration. This returns the App.Current.MainPage.Navigation when resolved by the Lazy<INavigation> in the Navigator.

Now create the following AutofacBootstrapper class.

namespace Silkweb.Mobile.Core.Bootstrapping
{
    public abstract class AutofacBootstrapper
    {
        public void Run()
        {
            var builder = new ContainerBuilder();

            ConfigureContainer(builder);

            var container = builder.Build();
            var viewFactory = container.Resolve<IViewFactory>();

            RegisterViews(viewFactory);

            ConfigureApplication(container);
        }

        protected virtual void ConfigureContainer(ContainerBuilder builder)
        {
            builder.RegisterModule<AutofacModule>();
        }

        protected abstract void RegisterViews(IViewFactory viewFactory);

        protected abstract void ConfigureApplication(IContainer container);
    }
}

This exposes one method called Run and 3 protected virtual methods. In ConfigureContainer we register the AutofacModule above. RegisterViews is abstract and must be implemented in order to register our view models and views with the View Factory. ConfigureApplication is also abstract and is where we should set the main page and anything else related to the application.

Change the application bootstrapper so that it derives from AutofacBootstrapper.

namespace Silkweb.Mobile.MountainForecast
{
    public class Bootstrapper : AutofacBootstrapper
    {
        private readonly App _application;

        public Bootstrapper(App application)
        {
            _application = application;           
        }

        protected override void ConfigureContainer(ContainerBuilder builder)
        {
            base.ConfigureContainer(builder);
            builder.RegisterModule<MountainForecastModule>();
        } 

        protected override void RegisterViews(IViewFactory viewFactory)
        {
            viewFactory.Register<MountainAreasViewModel, MountainAreasView>();
        }

        protected override void ConfigureApplication(IContainer container)
        {
            // set main page
            var viewFactory = container.Resolve<IViewFactory>();
            var mainPage = viewFactory.Resolve<MountainAreasViewModel>();
            var navigationPage = new NavigationPage(mainPage);

            _application.MainPage = navigationPage;
        }
    }
}

The MountainForecastModule now gets registered in ConfigureContainer, the view models and views get registered in RegisterViews and I create and set the main page in ConfigureContainer. Notice I am using the view factory to resolve the main page. I also pass an instance of App to the bootstrapper to ensure that we set its main page after it has been created.

Now we have our bootstrapper update the MountainForecastApp.cs to create an instance of the bootstrapper class in its constructor.

        public MountainForecastApp()
        {
            InitializeComponent();

            var bootstrapper = new Bootstrapper(this);
            bootstrapper.Run();
        }

Forecast Page

Now that we’ve got this in place we can focus on creating the Forecast page. First I need to extend the MoutainWeatherService with a method to return a forecast for a given area. Create the following ForecastReport model class in the Models folder of the applications shared PCL project.

namespace Silkweb.Mobile.MountainForecast.Models
{
    public class ForecastReport
    {
        public string Forecast { get; set; }
    }
}

Add the following method to IMountainWeatherService which returns a ForecastReport for a given area id.

ForecastReport GetAreaForecast(int id);

And then add the following implementation to MountainWeatherService.

public ForecastReport GetAreaForecast(int id)
{
    switch (id)
    {
        case 100 : return new ForecastReport { Forecast =  "Today will be fine and dry." };
        case 101 : return new ForecastReport { Forecast =  "Today will be wet and windy." };
        case 102 : return new ForecastReport { Forecast =  "Blizzards expected throughout the day." };
        case 103 : return new ForecastReport { Forecast =  "Today will be very cold with occasional snow snowers." };
        case 104 : return new ForecastReport { Forecast =  "High winds and white out conditions expected." };
        default:
            return null;
    }
}

Again I am just returning some dummy data here. We will be talking to a real web service later.

Now add this simple ForecastReportViewModel to the ViewModels folder.

namespace Silkweb.Mobile.MountainForecast.ViewModels
{
    public class ForecastReportViewModel : ViewModelBase
    {
        private string _forecast;

        public string Forecast
        {
            get { return _forecast; }
            set { SetProperty(ref _forecast, value); }
        }
    }
}

Notice here we are calling the SetProperty helper method to raise PropertyChanged when the Forecast changes.

And create a Xaml Content Page called ForecastReportView in the Views Folder.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="Silkweb.Mobile.MountainForecast.Views.ForecastReportView"
    Title="{Binding Title}">

    <Label Text="{Binding Forecast}" />

</ContentPage>

This simply binds a label to the Forecast property on the view model and also binds the page Title.

Now let’s update the bootstrapper to register these with the view factory.

protected override void RegisterViews(IViewFactory viewFactory)
{
    viewFactory.Register<MountainAreasViewModel, MountainAreasView>();
    viewFactory.Register<ForecastReportViewModel, ForecastReportView>();
}

And then update the MountainForecastModule class to register these new types as single instances. This will ensure that we only use one single instance of the ForecastViewModel and ForecastReportView.

namespace Silkweb.Mobile.MountainForecast
{
    public class MountainForecastModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            // service registration
            builder.RegisterType<MountainWeatherService>()
                .As<IMountainWeatherService>()
                .SingleInstance();

            // view model registration
            builder.RegisterType<MountainAreaViewModel>();

            builder.RegisterType<MountainAreasViewModel>()
                .SingleInstance();

            builder.RegisterType<ForecastReportViewModel>()
                .SingleInstance();

            // view registration
            builder.RegisterType<MountainAreasView>()
                .SingleInstance();

            builder.RegisterType<ForecastReportView>()
                .SingleInstance();           
        }
    }
}

Next we need to navigate from each MountainAreaViewModel to the ForecastViewModel. Update the MountainAreaViewModel by adding a Command called ShowForecastCommand and injecting INavigator.

namespace Silkweb.Mobile.MountainForecast.ViewModels
{
    public class MountainAreaViewModel : ViewModelBase
    {
        private readonly IMountainWeatherService _mountainWeatherService;
        private readonly INavigator _navigator;
        private readonly Location _location;

        public MountainAreaViewModel(Location location, 
            IMountainWeatherService mountainWeatherService,
            INavigator navigator)
        {
            _location = location;
            _navigator = navigator;
            _mountainWeatherService = mountainWeatherService;
            ShowForecastCommand = new Command(ShowForecast);
        }

        public string Name { get { return _location.Name; } }

        public ICommand ShowForecastCommand { get; set; }

        private void ShowForecast()
        {
            ForecastReport forecastReport = _mountainWeatherService.GetAreaForecast(_location.Id);

            _navigator.PushAsync<ForecastReportViewModel>(viewModel =>
                {
                    viewModel.Title = _location.Name;
                    viewModel.Forecast = forecastReport.Forecast;
                });
        }
    }
}

Note that previously we injected the IMountainWeatherService to demonstrate dependency injection. Now we are actually using it in the ShowForecast method to return the ForecastReport. We then call PushAsync on the navigator giving it ForecastReportViewModel as the type we wish to navigate to and also provide an action to set the state on the view model.

Now update the MountainAreasViewModel to bind to the ShowForecastCommand.

    <ListView ItemsSource="{Binding Areas}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextCell Text="{Binding Name}" Command="{Binding ShowForecastCommand}" />
            </DataTemplate>
    </ListView.ItemTemplate>

And now we should be good to go. Build the app and run it up in the iOS simulator.

1

Nothing much changed here. Now click or tap one of the mountain areas.

2

Hey! Now click or tap the back button and select another mountain area.

3

Cool, everything works as we expected. We are navigating between these pages just by specifying the view model type. We are also only using one single instance of the Forecast View and View Model and setting its state each time we use the view model.

But there’s one small detail I’ve noticed that’s not quite right. You’d normally expect to see an indicator against each mountain area to show that there is more detail. On the iPhone this is shown as a chevron on the right hand side like this.

5

But why is it not showing this? The reason is that unfortunately the Xamarin Forms team have not included this in the TextCell yet. What is missing is something called a ‘Disclosure’. It is however very easy to add this feature using a Custom Render.

Extending the TextCell to support a Disclosure

To add a Disclosure option to the TextCell create the following TextCellExtended class in the Core project within the Views Folder.

namespace Silkweb.Mobile.Core.Views
{
    public class TextCellExtended : TextCell
    {
        public static readonly BindableProperty ShowDisclosureProperty = 
            BindableProperty.Create<TextCellExtended,bool>(p => p.ShowDisclosure, default(bool));

        public bool ShowDisclosure
        { 
            get { return (bool)GetValue(ShowDisclosureProperty); } 
            set { SetValue(ShowDisclosureProperty, value); } 
        }
    }
}

All this does is extend TextCell and add a boolean BindableProperty called ShowDisclosure.

Now open up the iOS project and add the following DiscloseureTextCellRender class.

using Xamarin.Forms;
using Silkweb.Mobile.MountainForecast.iOS;
using Silkweb.Mobile.Core.Views;

[assembly: ExportRenderer (typeof (TextCellExtended), typeof (DiscolosureTextCellRenderer))]

namespace Silkweb.Mobile.MountainForecast.iOS
{
    public class DiscolosureTextCellRenderer : Xamarin.Forms.Platform.iOS.TextCellRenderer
    {      
        public override MonoTouch.UIKit.UITableViewCell GetCell (Cell item, MonoTouch.UIKit.UITableView tv)
        {                  
            var cell = base.GetCell (item, tv);

            var textCellExtended = item as TextCellExtended;

            if (textCellExtended.ShowDisclosure)
                cell.Accessory = MonoTouch.UIKit.UITableViewCellAccessory.DisclosureIndicator;  

            return cell;
        }
    }
}

This is fairly standard approach for creating custom renderers. More details on creating custom renderers can be found on the Xamarin Forms website here.

(Note: You can also find many more extended controls in the Xamarin Forms Labs project which includes a whole host of extended controls. I will be taking a look at this in a later post.)

Now update the MountainAreasView xaml to use our new TextCellExtended.

<?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:cv="clr-namespace:Silkweb.Mobile.Core.Views;assembly=Silkweb.Mobile.Core"
    x:Class="Silkweb.Mobile.MountainForecast.Views.MountainAreasView"
    Title="{Binding Title}">

    <ListView ItemsSource="{Binding Areas}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <cv:TextCellExtended Text="{Binding Name}"
                                     ShowDisclosure="True"
                                     Command="{Binding ShowForecastCommand}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

Now build and run the app again.

4

Yey! And it works. That’s much better.

The great thing about all this is that I now have a View Model first navigation framework in place that I can re-use for all my Xamarin Forms apps.

I hope you found this post useful.

66 thoughts on “Creating a Xamarin Forms App Part 6 : View Model First Navigation

  1. Great work Jonathan! Nice to see a ViewModel first approach with Xamarin Forms rather than the View approach which seems to be in all of the examples, that I’ve seen anyway. Great stuff!

    Like

    1. Thanks Stephen. Yeah many of the examples are just really really bad practice imo. I’ve been doing WPF and MVVM for quite a long time now and know that View Model first makes everything so much cleaner and simpler, and translates directly to Xamarin Forms. I also can’t understand why a lot of examples construct views in code rather than Xaml. Makes no sense to me when you have Xaml at your disposal. I can only conclude that the examples are written by developers who are unfamilar with Xaml.

      Like

  2. Jonathan,

    Just encountered a small bug in this code – PopModalAsync in your Navigator class is calling PopAsync on the Navigation class. This just needs to be changed to PopModalAsync.

    Like

  3. Good day Jonathan. Thanks for your tutorials. I applied the ViewModel first navigation described above in a project. I used a MasterDetail page as my home page. I get an error :

    Autoface.Core.DependencyResolutionException.

    The error occurs in the ViewFactory.cs file, on the line:
    var view = _componentContext.Resolve(viewType) as Page;

    I will appreciate any help I can get. Thanks

    Like

    1. Hi,

      This works for me. In the bootstrapper set up the main page like this:

      protected override void ConfigureApplication(IContainer container)
      {
      // set main page
      var viewFactory = container.Resolve();
      var mainPage = viewFactory.Resolve();

      var navigationPage = new NavigationPage(new Page()); // Dummy Page

      _application.MainPage = new MasterDetailPage()
      {
      Master = mainPage,
      Detail = navigationPage,
      IsPresented = true
      };
      }

      Hope this helps.
      Jonathan

      Like

      1. hi, the MasterDetailPage is showing, but further navigation is not working. The app crashes.
        I have a button in my Detail page, that call the navigation code.

        var viewFactory = container.Resolve();
        var mainPage = viewFactory.Resolve();

        var navigationPage = new NavigationPage(mainPage);
        var masterPage = new ContentPage();
        masterPage.Title = “asd”;
        _application.MainPage = new MasterDetailPage()
        {
        Master = masterPage,
        Detail = navigationPage

        };

        —-
        Navigation code in TestViewModel1:
        ButtonCommand = new Command(async()=>await _navigator.PushAsync());

        Like

  4. Hello Jonathan, this blog has been an amazing find and I really appreciate all the effort you have put into this project and your willingness to share. I have a question regarding navigation inside a Master/Detail page. I want to place a button on my detail page that when pressed navigates to a new page and will give me the back button. I am using your ShowWarnings example and the event is firing but the view does not change to the warnings view. I believe I need to get at this method App.MasterDetailPage.Detail.Navigation.PushAsync which is a Xamarin view first method but not sure how to do it in the viewmodel first setup. Hopefully you understand what I am trying to do. Would you have a simple solution you might be able to share?

    Like

      1. I’m assuming the scenario is a Master/Detail with NavigationPage as the Detail. In which case I have an updated regisration of Func to resolve the current page as follows:

        (please replace [] with chevrons as this editor doesn’t like chevrons)

        builder.RegisterInstance[Func[Page]](() =>
        {
        // Check if we are using MasterDetailPage
        var masterDetailPage = Application.Current.MainPage as MasterDetailPage;

        var page = masterDetailPage != null
        ? masterDetailPage.Detail
        : Application.Current.MainPage;

        // Check if page is a NavigationPage
        var navigationPage = page as IPageContainer;

        return navigationPage != null
        ? navigationPage.CurrentPage
        : page;
        }
        );

        Place this in the AutofacModule class to replace what went before or register this in your own autoface module.

        This caters for scenario’s of Master/Detail, Master\Detail with detail as NavigationPage, NavigationPage only, and none navigation page.

        Like

  5. View first has it’s place, and using it is not “bad practice”. Using VM first has it’s pros, but it has its drawbacks as well. I used to use VM first, but change to View first for a number of reasons. Not trying to change your mind, just point out that it’s not considered bad practice.

    I just wanted to point out that your navigation won’t work reliably, and your navigation scenarios are extremely limited, since you are depending on the App.Current.MainWindow.Navigation. Each Page has it’s own Navigation that is independent of other Pages, so you can’t rely on the MainPage alone. That is unless, you are only support that scenario. Then ignore what I said. That is why you see a lot of other examples that pass either the Page or INavigation to the ViewModel.

    Also, keep in mind, in Xamarin.Forms, Pages aren’t technically views, but rather a class that represents a view. The target platforms use renderers to interpret the Page code, and then render it respectively. So what you’re left with is an argument over the “view” concept in your ViewModels in a Xamarin.Forms app as opposed to an actual presentation element. I don’t feel strongly about it. Just something to think about.

    Good post!

    Like

    1. Brian, Thanks for your valued comments. I’d be interested to hear what the drawbacks are to VM first and why you changed to view first. Was this using XF or WPF or both? I’m not sure what you mean by App.Current.MainWindow.Navigation. The Navigator allows any page implementing IPage to be a valid navigator. I use PageProxy which simply resolves whatever you have defined as the Func. This is very adaptable to whatever page scenario you care to use and can be configured as such, i.e. current page navigator or whatever. But I realise there maybe cases where this could be an issue that I have not come across. I’d welcome any feedback where you think this might be an issue.
      By Views I am referring to the them in a generic sense, not in a XF sense, so Pages or Views or anything displayed in the UI is indeed a view. Indeed the target platforms uses renderers to interpret the page code, but it is important to drive the application from a view model perspective which will then resolve the appropriate view/page for the renderer to interpret. I do feel strongly about this because from experience I have seen that View First approach leads to a difficult to maintain codebase because your application logic is no longer driven by the application logic itself.

      Like

      1. I used to be a big proponent of VM first in my early days of enterprise WPF app dev. I should mention, that I use Prism to develop WPF apps. In Prism you navigate to a key, as you mentioned in your post. It is no different than how you register your VMs and Views with your ViewFactory, except you don’t create a coupling between either one. The apps I worked on were very large, and it became obvious that maintaining thousands of DataTemplates wasn’t going to work. Luckily, with Prism it doesn’t care if you use View or VM first, you simply navigate to the same key and switch out the appraoch. So luckily our VMs did not have to change, we just changed our registrations. With VM first, you create a coupling between the VMs, which is not desirable in the apps I worked on. Many times we were given a key to a view that existed in a separate, non-referenced, assembly. This kept our application very modular in nature. Then there was the fact about the performance impact having so many DataTemplates was having. We dramatically increased our app perf simply by switching to View first. So our view models were completely decoupled from everything; views and other view models. They were extremely test friendly, and very easy to maintain and extend. By switching to View first, we managed to become more efficient in all aspects of dev and maintenance. Debugging data templates can be a real pain.

        There were a number of other smaller issues that I can’t recall in detail, but vaguely remember saying, I’m glad I don’t have that issue anymore. In essence, it really is a personal choice, but both are relevant and good options. What really matters is that the VM remains decoupled from View, and preferably other VMs, and that all concerns of the MVVM pattern are being respected.

        As for as your IPage or PageProxy, I didn’t see that in this post. Did I miss it? I only say where you were registering your singletons with the Autofac container. I am personally in the process of trying to create a decoupled Navigation framework myself, and that is how I came across your post. I am trying to get a gauge on what the community feels about Xamarin.Forms navigation. I personally hate the fact that INavigation is so coupled to the Page, and I don’t want that in my VMs. I’m on the same side as you. Although technically it’s not a view, the concept is, and we should try to keep those separate.

        Right now my approach relies on the use of a ViewModelLocator, except not like you are probably used to. So static classes. This ViewModelLocator uses a container to resolve views and VMs. That’s the only reason I use it. Otherwise, I really despise ViewModelLocator :0)

        Like

      2. Brain, Thanks for sharing your experiences with both view and view model first. I have also worked with both approaches over the years on very large projects. I have also used Prism, so I guess we are similar in our background. Did you use Prism’s RegionManager for your Navigation in your WPF applications? I used to use this but don’t anymore because it creates more problems than it solves and is overly complex. In particular having to create RegionAdapters make it a real pain. The idea of using a Key though is perfectly fine and I would agree that it does allow you to switch view or view first approaches. However you still need to register the view against this key somehow. In Prism you’d do this through the container which the RegionManager looks up using the supplied key. How are you doing this?

        I would disagree however that View Models should not know or collaborate with other view models. There is nothing wrong with this and in fact it makes things a whole lot simpler and easier in many scenarios. How are you passing state to your other view models? I know that RegionManager tries to do this with an ugly Uri construct which really sucks. It is very common to have to pass state to the next view/view model and the navigation mechanism needs to be able to handle this. There are a couple of ways I do this. Either by having a Func supplied as a constructor parameter so that I can resolve the view model and give it the state, then navigate this view model using the Navigator, or I can set the state afterwards by supplying an Action when I call the navigator which will set some state on the view model. In either case we have view models collaborating which is absolutely fine. This is also very testable because the Func can be easily mocked, especially if the view model implements an interface.

        You mention DataTemplates being an issue. I’ve never really found this in WPF and find the benefits of resolving the View from the ViewModel and automatically setting the DataContext are worth it. There are other alternatives to view resolution using view model first. A named convention is one approach where you enforce the convention of xxxViewModel and xxxView in named folders. Or taking the approach I have taken here using a View Factory where you register your views and view models. This is not tightly coupling at all. Tight coupling is when you have one class know about the other. The view and the view model are completely decoupled. The ViewFactory merely provides a mapping from one to the other. With View First however this decoupling is often violated by setting the BindingContext (DataContext) in the constructor of the view. This forms a very tight coupling between view and view model. ViewModelLocator attempts to get around this, but in my opinion ViewModelLocator is just total filth and a really had idea. Not only is it a static class which uses the equally evil ServiceLocator, but you end up adding a property for every view model so it isn’t scalable. You’re better having a factory that will resolve the view model depending on the view type. I prefer however to do this the other way around because I believe it is important to drive the application logic from the view model and not from the view.

        The other benefit to view model first is dialog navigation. You may need to navigate to a model dialog to capture some information and then return to the view model to process the details which have been captured. I know Prism has the concept of InteractionRequests which are a totally over engineered approach to a simple task. Using View Model first and the help of an IDialogService you can easily provide the view model with some state, show the view model, handle the result and then query the state of the view model. There is absolutely nothing wrong with doing this.

        Clearly there is no real right or wrong here, just different approaches which work better in certain scenarios. However I do believe that it is important to always think from the perspective of the View Model, because the view is just a visualisation of that and is therefore secondary. That doesn’t mean that we don’t care about our views, they are indeed what we see as the end result which is ultimately what we are trying to achieve.

        Like

  6. I too have worked with both approaches. It’s far more natural to work with view-models in your code and just delegate the rendering of those VM’s to data templates. Every single view-first approach I’ve had the misfortune to work with has been clunky and lacking in elegance and it was only a matter of time before they were refactored to view-model first. I’ve never experienced any downsides, performance, maintenance or otherwise when using a view-model first approach.

    Like

    1. Yes, I make use of the regions and the navigation framework. I have personally never run into any problems with the navigation framework, and find it extremely simply. Create a region, and then navigate objects into it. It also gives me extreme flexibility when dealing with navigating different sections (regions) in a single view. Yes, RegionAdapters are required for 3rd party controls, but you only have to create them once, and you can also attached behaviors to them which is extremely powerful. Yes, I supply a key to the containers, which Prism then uses to resolve the type being request based on that key (View or ViewModel).

      In my scenarios ViewModels could not know about, or be coupled to, other ViewModels. In most of the cases these ViewModels didn’t even exist in the same assembly, and did not reference the other. Of course, I completely agree with you, collaboration and communication between those ViewModels is a must. Just not the coupling required by a hard reference between one VM to another VM. This goes back to what kind of app your writing and its requirements. The Prism navigation framework does not require you to use an URI construct to pass parameters anymore. You can pass any number of actual objects.

      I didn’t do a good job explaining what I meant by “coupling”. I was not saying your approach couples the VM to the View, I was saying you are coupling your VMs to other VMs. Your VM requires a reference to another VM in order to navigate. Which, is not a big deal if your app supports that architecture. I completely agree with you about ViewModelLocator. I hate static classes with a property for every VM, and every time you have a new VM, you have to go add it to the ViewModelLocator class. That totally sucks, and I can’t stand it. That’s why the ViewModelLocator I use is not a static class, but rather a convention based locator that utilizes an IoC container to resolve the VM and it’s dependencies.

      I suggest checking out this post on the ViewModelLocator I use. Notice that it’s not your normal ViewModelLocator and doesn’t have the issues most ViewModelLocators have. It’s just about setting the DataContext and that’s it.

      http://brianlagunas.com/getting-started-prisms-new-viewmodellocator/

      Doing View first has no impact showing dialogs. You show dialogs the same way that you suggest by using a dialog service in your VM. This does not change. Also, I agree with you regarding the Prism InteractionRequest. I can’t stand it. Super complicated for something I can easily do with a dialog service. But some devs that love Blend, love the InteractionRequest. I’m not one of them.

      I would like to point out that when we say View First or ViewModel First, we are simply talking about who is creating who. How is the DataContext being set. When I use View First, I don’t know that I am navigating to a “View” from within my VM. I just know I am navigating to something called “Admin”, and that object is shown in the UI. It could be a View, or a VM. I don’t know what it is and I am not concerned with it either. I always develop in the perspective of the VM, and never have to consider the View. I also don’t have to worry about being concerned with other VMs. I simply navigate to something, and my container provides the object I am asking for based on my registrations.

      A lot has probably changed since you last looked at Prism :0).

      Like

  7. hello,

    I was wondering how would go about making the navigation if for example in the listview item you have a template with two textboxes and an image, from what I know you cannot bind a command on the ItemTapped event from the listview

    Like

      1. thank you, that worked for me, I also tried making a custom listview with a bindable onItemTapped property but that was using the ListView viewModel instead of the Item ViewModel so it kinda defeated the purpose of having a separate viewmodel for the items

        Like

  8. hello,

    I have a question related to Autofac, I see registering interfaces with their implementations is preatty neat as long as they are in the same project, but what happens if I the implementation is different on each platform ? I made a module class for each platform which inherits from the main module in the portable class and made an override on the Load method calling the base from it, but I have no idea how will the platform know to run that file. In your app I see no such per platform implementations, if I missed them please point them out to me otherwise would be great if you could give me a hint on what to do next.

    thank you

    Like

    1. Sergiu, This a good point you’ve raised. There are a number of ways this can be done. I think it’s best to create a completely seperate Autofac Module for each platform project. You can then pass this to the application class when you create it. For example on iOS:

      LoadApplication(new MyApp(new iOSModule());

      and then forward this to the bootstrapper which would register this module.

      Or you could do it as a generic.

      LoadApplication(new MyApp[iOSModule]()); (read cheverons for [] as the wordpress editor doesn’t like cheverons)

      Or perhaps a more elegant way would be to have it auto registered using RegisterAssemblyModules. (More on this here http://docs.autofac.org/en/latest/register/scanning.html).

      But I think you would have to pass the executing assembly from the target platform something like this.

      LoadApplication(new MountainWeatherApp(System.Reflection.Assembly.GetExecutingAssembly()));

      and then in the bootstrapper do:
      builder.RegisterAssemblyModules(assembly);

      Entirely up to you how you do it though.

      Like

  9. Hi Jonathan,

    First of all, I want to thank you for your work. I am a (french) beginner in MVVM / WPF / Xamarin applications, and I really like your ViewModel first / navigation pattern. I understood a lot of things with your tutorials.

    I have one problem, let’s say that I have a BasketViewModel with products (count) property and a total price property.

    I would like to display thoses properties on a product page, or home page. Do I really need to inject BasketViewModel inside the ProductViewModel or HomeViewModel ? I would like to reduce coupling.

    The only way I found for now is to use a ViewModelLocator so that the views directly access to the BasketViewModel. But I am not comfortable with it, it doesn’t seems very “ViewModel first”.

    Like

    1. I would not recommend using any sort of service/viewModel locator pattern. You should use a dependency injection framework like Autofac and inject any dependencies into your constructors. I would recommend that you introduce an interface called something like IShoppingBasket, with properties for Count and Total Price, that your BasketViewModel should implement and register your BasketViewModel with your DI container against this interface. You can then inject IShoppingBasket into the constructor of your Product/Home ViewModels. This still keeps them nicely decoupled from your BasketViewModel and is easily testable.

      Liked by 1 person

  10. thank you for the ideas !

    for anyone interested I went with the first one, namely I added a param in the app constructor and sent it to the bootstrapper:

    public App(MyAppModule module)
    {
    var bootstrapper = new Bootstrapper(this, module);
    bootstrapper.Run();
    }

    where it gets registered:

    private readonly MyAppModule _module;

    public Bootstrapper(App application, MyAppModule module)
    {
    _application = application;
    _module = module;
    }

    protected override void ConfigureContainer(ContainerBuilder builder)
    {
    base.ConfigureContainer(builder);
    builder.RegisterModule(_module);
    }

    and on each platform the module class inherits from MyAppModule (main app module) and has the Load method implemented like so:

    public class MyAppiOSModule : MyAppModule
    {
    protected override void Load(ContainerBuilder builder)
    {
    base.Load(builder);

    //builder.RegisterTypes here
    }
    }

    Like

  11. Based on our discussions, I have added the ability to conceptually navigate to ViewModels in Prism for Xamarin.Forms too :0)

    NavigationService.Navigate();

    Now devs have a choice; keys or classes!

    Like

  12. Hi, first of all thanks a lot for these great examples on using Autofac and proper ViewModel first navigation.
    I’m trying to make it possible to pass data when pushing a ViewModel, and returning data when popping a ViewModel.

    I’d like to do this by adding a property to the ViewModel which keeps track of the previous viewmodel.
    Then the viewmodel would get Init(object data) and Reinit(object data) methods that will be called when pushing or popping the view.
    Could you help me out implementing this in the Navigator?

    Like

    1. Hi,

      Not sure how you’d go about this, but I guess you can call these methods from the navigator when pushing or popping provided they are part of your ViewModel base class or interface. I be interested to hear what you come up with.

      Like

  13. Jonathan, I didn’t found where can I implemente the following events:

    protected override void OnStart()
    {
    }

    protected override void OnSleep()
    {
    }

    protected override void OnResume()
    {
    }

    is it on the MountainForecastApp.xaml.cs ?

    could you give a hint of where can I implemente these events of the app ?

    Like

      1. Thanks guy, I was using your examples from post #6 witch wasn`t using an old version of XF.
        Just used your code from post #12 and find out the answers. Tnks as lot.

        Like

  14. Hi,

    Have been trying to implement the Navigation here as it made my ViewModels unit testable. However, when I try to push to the next view model, the model class being passed in has null values.

    I use this ode to move to the next page :

    await Navigation.PushAsync(vw =>
    {
    vw.GroupName = newGroup.Name;
    vw.GroupPin = newGroup.Pin;
    });

    in debug if I check that there are values and thrre sre, but when I get to the target view, the view model passed in has no values.

    public NewGroupCreatedPage(NewGroupCreateViewModel viewModel)
    {
    BindingContext = viewModel;
    HeaderText = “Group Created”;
    ShowHeader = true;
    var closeBtn = new Button { Text = “Close”};
    }

    Have you come accross this issues? Anything simple I am missing??

    Cheers Ash…

    Like

    1. Hi Ash,

      I see you are passing the view model to the page constructor. I think this is the problem. The view model should not be passed to the view constructor. The BindingContext of the view/page is set by the ViewFactory which the Navigator uses to resolve the view and hook them together. I suspect what is getting injected into your page is another new instance of the view model, not the one used in the navigation.

      Hope this helps.

      Jonathan

      Like

  15. This is great stuff, thank you! Can the same approach be used for multiple navigation stacks … say if a TabbedPage is used where each tab is its own NavigationPage or modal popups that will navigate to new pages?

    Like

  16. Hi Jonathan,
    Thank you for writing. I like your architecture and even like when you deviate from ‘best practice’. Deviating from best practice with a reason shows through understanding of the best practices. From this professional respect, I would like to know you opinion on something. Why do you need a state in the VM? Another way to put it, why does Devin (a comment above) need to pass information from one VM to another VM?

    In my code, my model layer is not just for data, it’s also for logic and state of the application. When I feel the need to pass state from a VM to another VM, I look for a model class that I am missing. If I had a model class with that information, then both VM would work with that model class and not need each other.
    One of my first WPF MVVM applications, also had the requirement that it had to run with other interfaces, a command line interface, and an API through a TCP connection. This made me have all the state, data, logic, and validation in the model layer. The WPF app just added VMs and Views, the command line app just added the command line processing of strings. I am wondering now if this experience has led me to push to much into the model layer and have too simple VMs.

    I would really appreciate your thoughts on this. It’s hard to find somebody on the web or in person that is not creating VM inside their views and then pass ‘this’ to the VM constructor.

    Thanks,
    Juan Carlos

    Like

    1. Juan,

      I guess at the end of the day it really depends on your application. By state I am assuming we are talking about the Model here. The model is generally passed to the View Model so that it can expose or adapt it for the view. Whether that model is a simple DTO or a complex business model with business logic entirely depends on your application. A service which retrieves data can also be classed as a model to. In the case of my weather application I am dealing with simple DTO’s returned from a web service. They contain no business logic. As for passing state from one view model to another this is a fairly common scenario where you have a hierarchy of View models. The parent VM may retrieve data from a web service and then create a list of child view models from that data. It would therefore need to pass that part of the model to each child view model. You could go down the route of creating factories or builders for this purpose but I think that may just make things more complex that needed. You have to be careful however with logic in the model and not have logic that is concerned with the view like commands or property changed notifications. Maintaining application state within the model is perfectly fine though.

      Like

      1. I see. We are not thinking too differently then. I’ll continue on with this great weather app example. Thank you.

        Like

  17. Hi Juan,

    That’s what I ended up doing as well, it seems only logical to keep this in a central place like the model, to be able to keep your VM’s light and free of business logic.

    But I as well would like Jonathan’s thoughts on this.

    Devin

    Like

  18. Hi Jonathan,

    I’ve used your example to setup a project (my first project in Xamarin by the way), and trying to adapt it to fit our needs.

    What I have is a master/detail page, with the detail page being a Navigation page. What I did to have my navigation working was to change the AutofacModule to register the Detail navigation of the master page instead of the main page’s navigation. That seemed to work well with only one menu in my application.

    I then tried to add a second menu, which creates a new navigation page (with the correct content page) to replace the Detail of the master page. From there, I’ve never been able to have all my pages working, the commands that call the navigator never seem to be able to push (or pop).

    I hope I’m providing the necessary information for an answer on this… In any case, how would you go to implement this in a master/detail setup where the navigation resides in the Details page of the master page ?

    Thanks in advance for your thoughts,
    Bruno

    Like

    1. Good question. I updated the default page resolver to try to cater for this scenario in the AutofacModule Load method.

      (Substitute [] for due to Worldpress glitch).

      // default page resolver
      builder.RegisterInstance[Func[Page]](() =>
      {
      // Check if we are using MasterDetailPage
      var masterDetailPage = Application.Current.MainPage as MasterDetailPage;

      var page = masterDetailPage != null
      ? masterDetailPage.Detail
      : Application.Current.MainPage;

      // Check if page is a NavigationPage
      var navigationPage = page as IPageContainer[Page];

      return navigationPage != null
      ? navigationPage.CurrentPage
      : page;
      }
      );

      This tries to work out things out but I’ve not tested it thoroughly as I’m not currently using it like you are. You can always override this in your own Autofac module by registering Func[Page]] with your own logic or just amend the one above.

      Update: This post seems to answer the question of the above working in this scenario.
      http://stackoverflow.com/questions/33164175/using-navigation-in-masterdetailpage-with-autofac-and-xamarin-forms

      Thanks to all those trying and testing this. Nice to know folk are using this.

      Hope this helps.

      Like

  19. My application has a NavigationPage as base, but deeper into the application there is a part where a MasterDetailPage is needed.

    I’ve pushed this page modally, and was able to get the menu navigation working based on this post: http://stackoverflow.com/questions/33164175/using-navigation-in-masterdetailpage-with-autofac-and-xamarin-forms.

    The Detail page is a NavigationPage. But when I try to Push a new viewmodel from the Detail viewmodel, it get’s pushed on the base NavigationPage, instead of the one in the Detail page. Because the MasterDetailPage is modal, the viewmodel is pushed behind it.
    How can I fix this?

    Like

  20. Hi Jonathan. I have one question for you. View Model First Navigation you create ShowForecastCommand in MountainAreaViewModel,
    public class MountainAreaViewModel : ViewModelBase
    {
    private readonly IMountainWeatherService _mountainWeatherService;
    private readonly INavigator _navigator;
    private readonly Location _location;

    public MountainAreaViewModel(Location location,
    IMountainWeatherService mountainWeatherService,
    INavigator navigator)
    {
    _location = location;
    _navigator = navigator;
    _mountainWeatherService = mountainWeatherService;
    ShowForecastCommand = new Command(ShowForecast);
    }

    public string Name { get { return _location.Name; } }

    public ICommand ShowForecastCommand { get; set; }

    private void ShowForecast()
    {
    ForecastReport forecastReport = _mountainWeatherService.GetAreaForecast(_location.Id);

    _navigator.PushAsync(viewModel =>
    {
    viewModel.Title = _location.Name;
    viewModel.Forecast = forecastReport.Forecast;
    });
    }
    }
    But this command binding on MountainAreasView where BindingContext = MountainAreasViewModel.
    How you called ShowForecastCommand command on the side MountainAreasViewModel?

    Like

  21. HI Jonathan,

    First I want to tank you for this incredible tutorial. Second i want to ask you which you consider to be the best MVVM approach to use an TabbedPage with all this stuff integrated. I’ve tried in multiple ways but without success yet. First solution was to create an ObservableCollection of Pages in the view model and bind that collection to ItemsSourceProperty of the TabbedPage. I’ve defined a DateTemplate for the ItemTemplate and with a binding like this: SetBinding(ViewWithBinding.BindPageProperty, new Binding(“.”)) i can get the instance of the page but i don’t know how to display it in the user interface. The second solution is to create a viewModels observable collection and use viewFactory to create the coresponding views in the data template, but i was unable to set what DataTemplate displays. I’m using code behind to define the interface, because the project was started in this manner before i’ve stated working on in.

    Best regards,

    Lucian.

    Like

  22. Hi Jonathan,

    I’m trying to implement your ViewModel first navigation in my app and get the following run-time exception when building the container:

    The type ‘Xxx.Factories.ViewFactory’ is not assignable to service ‘Xxx.Factories.IViewFactory’.

    Can you please help?

    Like

  23. Hi,

    I notice that when you create your viewmodel in this chapter you said “Notice here we are calling the SetProperty helper method to raise PropertyChanged when the Forecast changes.”, however, I notice that in later chapters (like adding the Hazards) you no longer seem to be adding calls to SetProperty.

    In fact I can’t see where you are making calls to PropertyChanged at all in these later examples.

    Is there a reason for this change?

    Thanks Ash…

    Like

Leave a comment