Creating a Xamarin Forms App Part 12 : Extending the User Interface.

  • 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

This is the final post in this series, which wraps up some of the UI not yet implemented for my Mountain Weather Application so far. This is not to say that this is the end of this App, far from it. Future posts will feature this app and it’s progress but I’d like to conclude this series with this post.

So far my app is displaying the mountain weather forecast information from the Met Office Data Point service for all the mountain regions in the UK, with one exception. The forecast data includes Hazard information for each area, which includes a textural description of each Hazard together with a Risk of High, Medium, Low and No Risk. This really warrants a separate page, as the information is quite extensive. I therefore need to be able to navigate from the forecast page to the Hazards page for each area forecast.

Firstly lets create a new Hazards Page. Given that the Hazard Model looks like this,

    public class Hazard
    {
        public short No { get; set; }

        public string Element { get; set; }

        public Risk Risk { get; set; }

        public string Comments { get; set; }
    }

I need a new HazrdsViewModel, which looks like this:

    public class HazardsViewModel : ViewModelBase
    {
        public HazardsViewModel(ForecastReport forecastReport)
        {
            var hazards = forecastReport.Hazards.Where(hazard => hazard.Risk != Risk.None).ToList();
            if (hazards.Any())
            {
                Hazards = hazards;
                Risk = hazards.Max(x => x.Risk);
            }

            Title = "Hazards";

            var date = forecastReport.ForecastDay0.Date;

            Date = string.Format(date.ToString("dddd d{0} MMMM"), date.DaySuffix());

            IssuedBy = string.Format("Issued by The Met Office on {0} at {1}",
                string.Format(date.ToString("d{0} MMM"), date.DaySuffix()),
                string.Format(date.ToString("hh:ss")));

            Area = forecastReport.Location;
        }

        public string Date { get; set; }

        public string IssuedBy { get; set; }

        public string Area { get; set; }

        public IEnumerable<Hazard> Hazards { get; private set; }

        public Risk Risk { get; set; }

    }

Here I am exposing the Hazards via the Hazards property and adding some additional date, IssuedBy and Title information.

For the view I want to display the Hazards in a list, where each item will have a header for the Hazard Element that will have a background colour of Red for High Risk, Orange for Medium Risk and Yellow for Low Risk. I initially thought that this would be an excellent candidate for the new Style.Triggers in Xamarin Forms 1.3. However I discovered that there is a bug with this in that you can’t add more than one trigger without it blowing up, more on this here.

So I created a RiskToColorConverter that allows me to specify the colours for each Risk Type for both Background and TextColor properties. Here’s the converter:

    public class RiskToColorConverter : IValueConverter
    {
        public Color HighColor { get; set; }

        public Color MediumColor { get; set; }

        public Color LowColor { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (!(value is Risk))
                return Color.Default;

            var risk = (Risk)value;

            switch (risk)
            {
                case Risk.High:
                    return HighColor;
                case Risk.Medium:
                    return MediumColor;
                case Risk.Low:
                    return LowColor;
                default:
                    return Color.Default;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }  

Here I provide 3 properties to set the Color for each Risk and then simply do the conversion in the Convert Method. I can then use this in my HazardView like so.

<?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.MountainWeather.Views.HazardsView"
    xmlns:ex="clr-namespace:Silkweb.Mobile.Core.Extensions;assembly=Silkweb.Mobile.Core" 
    xmlns:cv="clr-namespace:Silkweb.Mobile.Core.Views;assembly=Silkweb.Mobile.Core"
    xmlns:converters="clr-namespace:Silkweb.Mobile.MountainWeather.Converters;assembly=Silkweb.Mobile.MountainWeather"
    xmlns:model="clr-namespace:Silkweb.Mobile.MountainWeather.Models;assembly=Silkweb.Mobile.MountainWeather"
    xmlns:behaviors="clr-namespace:Silkweb.Mobile.Core.Behaviors;assembly=Silkweb.Mobile.Core"
    Title="{Binding Title}" BackgroundColor="{ex:ApplicationResource backgroundColor}" Padding="5">

    <ContentPage.Resources>
        <ResourceDictionary>

            <converters:RiskToColorConverter x:Key="riskToBackgroundColorConverter" HighColor="Red" MediumColor="#FF6600" LowColor="Yellow" />
            <converters:RiskToColorConverter x:Key="riskToTextColorConverter" HighColor="White" MediumColor="White" LowColor="Black" />

            <DataTemplate x:Key="hazardTemplate">
                <StackLayout Spacing="0" Padding="0,0,0,10">
                    <ContentView BackgroundColor="{Binding Risk, Converter={StaticResource riskToBackgroundColorConverter}}">
                        <ContentView Padding="5">
                            <Label Text="{Binding Element}" Style="{StaticResource mediumHeaderStyle}"
                                   TextColor="{Binding Risk, Converter={StaticResource riskToTextColorConverter}}" />
                        </ContentView>
                    </ContentView>

                    <ContentView BackgroundColor="White">
                        <ContentView Padding="5">
                            <Label Text="{Binding Comments}" Font="Small" />
                        </ContentView>
                    </ContentView>

                </StackLayout>
            </DataTemplate>

        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <StackLayout Spacing="0">
            <Label Text="{Binding Date}" Style="{StaticResource largeHeaderStyle}" />
            <Label Text="{Binding IssuedBy}" Style="{StaticResource microTextStyle}"  />
        </StackLayout>

        <ScrollView Orientation="Vertical">
            <StackLayout Orientation="Vertical">
                <StackLayout.Behaviors>
                    <behaviors:ItemsSourceBehavior ItemsSource="{Binding Hazards}" ItemTemplate="{StaticResource hazardTemplate}" />
                </StackLayout.Behaviors>
            </StackLayout>
        </ScrollView>
                                                
    </StackLayout>

</ContentPage>

There’s a few things here worth noting. Firstly I’m using the Converter to define both the Background and TextColor for my Headers by defining the two converters. Then Notice the DataTemplate for each item uses a Label wrapped in ContentView that is wrapped in another ContentView. The reason for this is that for some reason Xamarin Forms does not include a Margin property which means we have to rely on the Padding of an outer control, which means placing the Label in the lowest common denominator control for this which is ContentView . I have also made use of the ItemsSourceBehavior for the Hazards which I mentioned in an earlier post. I also discovered a bug with the new Behavior<T> class mentioned here. Notice that I am simply using a StackLayout in a ScrollView with this Behavior attached.

All this is well a good, but how do I actually display this view from my forecast page? I decided the best solution was to make use of the Toolbar and add an item to allow me to navigate to the Hazards for the Area I have selected. This is achieved by simply adding a ToolbarItem to the ForcastReportView as follows:

    <ContentPage.ToolbarItems>
        <ToolbarItem Name="Hazards" Command="{Binding ShowHazardsCommand}" />
    </ContentPage.ToolbarItems>

And then adding a ShowHazrdsCommand to the ForecastReportViewModel like this.

        public ICommand ShowHazardsCommand { get; set; }

        ShowHazardsCommand = new Command(ShowHazards);

        private void ShowHazards()
        {
            if (_hazardsViewModel == null)
                _hazardsViewModel = new HazardsViewModel(_forecastReport);

            _navigator.PushAsync<HazardsViewModel>(_hazardsViewModel);
        }

This simply uses the INavigator to navigate to the HazardsViewModel. I also need to add the following to my Bootstrapper class to map the View to the ViewModel.

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

Now when I display the Forecast page for an area I see the Hazards Toolbar Item like this.

Screen Shot 2015-01-13 at 22.25.46

and when I tap on the ‘Hazards’ toolbar item it navigates to the Hazards view like this.

Screen Shot 2015-01-13 at 22.25.58

Just as well cos it looks like a pretty stormy and snowy day out there just now !!

This concludes this series on ‘Creating a Xamarin Forms App’, I hope you enjoyed it as much as I have. There is much more I still want to do with this app before it sees the Apps Stores, which I will feature in future posts on this blog. But for now I think this demonstrates a great first step in my Adventures with Xamarin Forms.

35 thoughts on “Creating a Xamarin Forms App Part 12 : Extending the User Interface.

  1. Good article. I’m in the fortunate position of having seen this application running on an iPhone and it’s very professional, performant and slick. Well done mate.

    Like

  2. The Final version uploaded at GitHub, is working?
    I have tried to build the solution, but I couldn’t because all PNGs of Resources/drawable are missing

    Like

  3. Hi Jonathan,what an awesome series – I’ve learned a huge amount going through all of it and have restructured much of my app following your guidelines (although with just one PCL…for now). One challenge that I’m facing now, and one of the few you didn’t touch one, is using AutoFac with the Xamarin TabbedPage.

    By default the TabbedPage has pages added to it (either in code or via XAML) but when I do that now it bypasses all the goodness that comes from driving the UI from the VM. I’ve trying to work out exactly how I would go about using the view factory to resolve the VM back into the page reference I need but from within the TabbedPage class I can quite wrap my head around how I can get to the viewFactory…which may be the wrong approach in the first place(?).

    My TabbedPage, via it’s associated VM, is what’s set as the MainPage for the app via the Bootstrapper. The trick is that its tabs need to reference(?) 4 or 5 other VMs instead of the normal page references and I can’t quite get this going. Any help/insight you could provide would be greatly appreciated!

    Like

    1. Ken,

      Really nice to hear you like my series. For an MVVM solution for TabbedPage all you need to do is compose your ViewModel that represents the TabbedPage of other child view models which represent the tabs. You can either represent this as a list of view models and bind this to the ItemsSource of the TabbedPage and supply an ItemTemplate in the Xaml (more on this here http://iosapi.xamarin.com/?link=T%3aXamarin.Forms.TabbedPage). Or you can simply define properties on your main ViewModel for each page view model to represent each page and define the tabs on the TabbedPage in the xaml and then bind these to the appropriate properties using BindingContext for each tab. You can resolve each child view model in the main view model by way of dependency injection using AutoFac and create a Func if you need to pass any state to these. Hope this helps.

      Liked by 1 person

      1. Hi Jonathan,

        Thanks for the quick reply!! I must admit, being fairly new to Xamarin Forms and *brand new* to AutoFac, I’m having a bit of trouble translating your suggestion – it *seems* like it should be fairly straight forward, but I’m not quite connecting the dots.

        Looking at the example you pointed me to, it was enlightening to find out that tabs *could* be created just through binding – cool! My issue seems fundamental though; the examples I’ve seen (including that link) are more-or-less directly adding ContentPage instances to the TabbedPage – I’m not quite getting how to get from MyTab1ViewModel to MyTab1Page so it can be added.

        From your description it seems I’m not connecting how in MyMainTabbedPageViewModel I’m able to resolve references to MyTab1ViewModel, MyTab2ViewModel (etc.) so they’re added as children of the TabbedPage, either directly or via the ItemSource trick. I’m not seeing how I can get to the ViewFactory from MyMainTabbedPageViewModel … or if that’s just me further misinterpreting your suggestion.

        Sorry to come across quite so dense – just wading through a lot of new [to me] concepts all at once.

        Thanks again, both for the articles and your help over this little hurdle.

        Ken

        Like

      2. Ken,

        To resolve your child vm’s just inject them into the constructor. You don’t need the ViewFactory in this case because you can define the view for the tabs as part of the tabbedpage. If you bind ItemsSource to a list of child vm’s then set the ItemTemplate to the page you wish to bind the child vm’s to. Alternatively just define properties on your MainViewModel for each child vm and then define tabs explicitly on the tabbed page and bind the binding context for each of these to to each property.

        Like

      3. Ok, while not nearly as elegant as what I believe you were suggesting, it does get me up and running – I’m sure I’ll want to refactor it as I learn more…sometimes this feels like the “old days” – Z80 assembler old days.. 😉

        Here’s what I’ve done in the ConfigureApplication() method of the Bootstrapper. There’s a lot I’m not happy with, but it’s working and I can move forward:

        var viewFactory = container.Resolve();
        var mainPage = viewFactory.Resolve(); // get the TabbedPage

        var dashPage = viewFactory.Resolve();
        dashPage.Title = “Dashboard”;
        dashPage.Icon = “Dashboard.png”;

        var journalPage = viewFactory.Resolve();
        journalPage.Title = “Journal”;
        journalPage.Icon = “Journal.png”;

        var restaurantsPage = viewFactory.Resolve();
        restaurantsPage.Title = “Restaurants”;
        restaurantsPage.Icon = “Restaurant.png”;

        ((MainNavPage)mainPage).Children.Add(dashPage);
        ((MainNavPage)mainPage).Children.Add(journalPage);
        ((MainNavPage)mainPage).Children.Add(restaurantsPage);

        Like

      4. Ken,

        I don’t think you need to wire up your Main ViewModel in the bootstrapper like this. You can inject the child view models into the main view model something like this:

        public class MainViewModel : ViewModelBase
        {
        public MainViewModel(
        DashboardViewModel dashboardViewModel,
        JournalViewModel journalViewModel,
        RestaurantsViewModel restaurantsViewModel)
        {
        Dashboard = dashboardViewModel;
        Journal = journalViewModel;
        Restaurants = restaurantsViewModel;
        }

        public DashboardViewModel Dashboard { get; set; }

        public JournalViewModel Journal { get; set; }

        public RestaurantsViewModel Restaurants { get; set; }
        }

        And then define your MainPage something like this in Xaml:

        (Note that wordpress has trouble displaying cheverons, so I’ve substituted them with [ and ] in all the following code. Hope this isn’t to confusing)

        [TabbedPage]
        [TabbedPage.Children]
        [DashboardPage BindingContext=”{Binding Dashboard}” /]
        [JournalPage BindingContext=”{Binding Journal}” /]
        [RestaurantsPage BindingContext=”{Binding Restaurants}” /]
        [/TabbedPage.Children]
        [/TabbedPage]

        Obviously you also need to create the respective Dashboard, Journal and Restaurants ViewModels and Pages, and register the ViewModels in your AutofacModule like this:

        builder.RegisterType[MainViewModel]();
        builder.RegisterType[DashboardViewModel]();
        builder.RegisterType[JournalViewModel]();
        builder.RegisterType[JournalViewModel]();
        builder.RegisterType[MainView]();

        An alternative neat trick to have these auto-registered with Autofac is to use this code which will Auto-register all your ViewModels without having to register them individually.

        builder
        .RegisterAssemblyTypes(typeof(MainViewModel).GetTypeInfo().Assembly)
        .Where(i =]; i.IsAssignableFrom(typeof(ViewModelBase)))
        .AsSelf();

        and finally in your bootstapper you can create the mainPage like this:

        protected override void RegisterViews(IViewFactory viewFactory)
        {
        viewFactory.Register[MainViewModel, MainView]();
        }

        protected override void ConfigureApplication(IContainer container)
        {
        var viewFactory = container.Resolve[IViewFactory]();
        var mainPage = viewFactory.Resolve[MainViewModel]();
        _application.MainPage = mainPage;
        }

        Hope this helps.

        Here’s a code snippet link for this code here.

        Like

      5. Hi Jonathan,

        Thank you so much for your patience and suggestions. Neat trick with the automatic registration of the VMs – I have more than a dozen of them in this app [so far], along with their associated Views/Pages, which is also why I was resistant to injecting them all through the constructor (just felt “messy” injecting so many individual tabs that way [what had me thinking of just injecting a collection of pocos representing the pages…].

        I ended up with a workably clean structure based on a sub-class of TabbedPage where I could add a little tab-registration plumbing. I still like the automatic VM thing though so am going to take a closer look at that, if for no other reason than it would help with ongoing maintenance.

        Again, thanks MUCH for you input on this and the articles that got me started on this path. I’ll look forward to following your ongoing adventures in Xamarin 🙂

        Ken

        Like

      6. Ken,

        Good to hear you are making progress.

        (Again I am replacing chevrons with [] to overcome wordpress issues).

        If you have so many tabs/childViewModels then you can take adventage of autofac’s ability to resolve and inject all of these as IEnumerable[T].

        (More on this here http://autofac.readthedocs.org/en/latest/resolve/relationships.html?highlight=ienumerable#enumeration-ienumerable-b-ilist-b-icollection-b).

        This would work really well with the autoregistration to. Let’s say that all your child view models for each tab implement ITabViewModel.
        The correct syntax to auto register this:

        builder.RegisterAssemblyTypes(this.GetType().GetTypeInfo().Assembly)
        .AssignableTo[ITabViewModel]()
        .As[ITabViewModel]();

        where ‘this’ is the Autofac Module you’ve defined in the same assembly as the viewmodels.

        Then you can inject these like this:

        public class MainViewModel
        {
        public MainViewModel(IEnumerable[ITabViewModel] items)
        {
        Items = items;
        }

        public IEnumerable[ITabViewModel] Items { get; private set; }
        }

        Then define your MainPageView xaml like this:

        [TabbedPage ItemsSource=”{Binding Items} ItemTemplate=”{StaticResource itemTemplate}” /]

        The slightly tricky bit here is the itemTemplate. The Xamarin Forms TabbedPage ItemTemplate only allows you to define a single DataTemplate for all the items. This is fine if all the items are the same type, but if they are all different, which is most likely to be the case it doesn’t provide support for a Template selector. We can easily get around this by creating a Page that looks up the View when it’s BindingContext changes using the ViewFactory. (I took this idea from this excellent article http://www.codeproject.com/Articles/818496/Using-MVVM-to-create-Tabbed-Interfaces-with-Calciu).

        The Page would look something like this.

        public class ViewSelectorPage : ContentPage
        {
        private readonly IViewFactory _viewFactory;

        public ViewSelectorPage()
        {
        _viewFactory = ViewFactory.Instance;
        BindingContextChanged += OnBindingContextChanged;
        }

        void OnBindingContextChanged(object sender, EventArgs e)
        {
        if (BindingContext == null)
        {
        Content = null;
        return;
        }

        if (Parent != null && Parent.BindingContext == BindingContext)
        return;

        View view = _viewFactory.Resolve(BindingContext);

        if (view != Content)
        Content = view;
        }
        }

        Notice however that here viewFatory.Resolve is returning a View, not a page. You’d need to update the viewFactory class so that it can support registering and resolving both Pages and Views. The common class for these being VisualElement or ILayout.

        So now you can define the DataTemplate in the Resources like this:

        [DataTemplate x:Key=”itemTemplate”]
        [views:ViewSelectorPage Title=”{Binding Title}” /]
        [/DataTemplate]

        In fact I like this so much I’m going to include it myself. I think I may even do a blog post on this 🙂

        Let me know how you get on and if this works for you.

        Liked by 1 person

  4. Hi Jonathan,

    Some awesome suggestions there – thank you so much! Glad I could help you come up with a new blog post too 😉

    There’s clearly a lot of depth in AutoFac that would be worth spending some time getting more familiar with and the notion of combining the set-based registration with a DataTemplate has some very interesting implications, particularly for apps with a large number of Views to manage.

    Since my environment is “stable” at the moment, I’m going to circle back to this topic to refactor once I have a few more of the trickier bits resolved. I was surprised (and pleased) to see you were also playing with some of they Syncfusion controls – I had already selected a couple of their graphing components for my UI design but hadn’t found many example of people actually using them in XF; seeing that you’ve done so helps with the confidence level there.

    Besides being just an excellent example of handling a lot of “real world” issues in a XF app, your Mountain Weather app just looks like something I would have loved to have used. I practically grew up on skis, mostly around Blackcomb and Whistler in British Columbia, Canada 🙂

    Like

  5. Hi Jonathan,

    Thanks for all these posts, you did an amazing job!!! They really helped me to start with Xamarin in a clear and efficient way…

    I have an application with a service that basically streams sound on the audio output (using Android native AudioTrack methods). I also have a storage service that is responsible to load/save some data in a file. Those services are registered in the IoC (autofac) and injected into ViewModels.

    When the application goes in a sleep state, I should stop the sound service and store the unsaved data. I hesitate between two ways of doing it:
    – Sending message using MessagingCenter from the OnSleep method to notify registered ViewModels. ViewModels are then responsible to “dispose” what they need (save/stop,…)
    – Retrieving services stored in the IoC in the OnSleep method and “dispose” them directly. It requires to have an access to the Container in the OnSleep method

    What would you recommend? And moreover, do you have any thoughts or advice concerning the application lifecycle in general?

    Thanks again for you work and cheers!
    Fred

    Like

  6. Hi Jonathan,

    Thanks for all these posts, you did an amazing job!!! They really helped me to start with Xamarin in a clear and efficient way…

    I have an application with a service that basically streams sound on the audio output (using Android native AudioTrack methods). I also have a storage service that is responsible to load/save some data in a file. Those services are registered in the IoC (autofac) and injected into ViewModels.

    When the application goes in a sleep state, I should stop the sound service and store the unsaved data. I hesitate between two ways of doing it:
    – Sending message using MessagingCenter from the OnSleep method to notify registered ViewModels. ViewModels are then responsible to “dispose” what they need (save/stop,…)
    – Retrieving services stored in the IoC in the OnSleep method and “dispose” them directly. It requires to have an access to the Container in the OnSleep method

    What would you recommend? And moreover, do you have any thoughts or advice concerning the application lifecycle in general?

    Thanks again for you work and cheers!
    Fred

    Like

    1. Hi Fed,

      Sorry it’s taken me a while to reply, just so busy.

      I’m not sure what the best approach for this is to be honest. I guess viewModels should be able to know about the app going into sleep mode but I’ve not look at this yet. Did you manage to resolve this as it would be interesting to hear how you got on.

      Autofac does provide lifetime management options (http://docs.autofac.org/en/latest/lifetime/instance-scope.html) which may prove useful.

      Let me know how you got on.

      Like

  7. Hi Jonathan,

    First of all, thank you for these amazing series, i’ve learned a lot about some of the best practices concerning not only Xamarin Forms development, but development in general.

    Since you come from a WPF background, what do you make of this:
    http://brianlagunas.com/first-look-at-the-prism-for-xamarin-forms-preview/

    Being just a preview, the sample uses Unity for DI, but basically it follows everything you demonstrated here. What do you make of it?

    Thanks once again!

    Nuno

    Like

  8. Hi,

    Don’t worry about that, it’s the sickness of all developers 😉

    It’s also what I was thinking… I didn’t implement or test anything related to lifetime yet (because I have some issues that I have to solve first), but as soon as I will test something, I’ll keep you informed.

    Thanks and cheers!

    Like

  9. Hi, this is an absolutely great workup and I have used your techniques in two apps so far (one of which is on the app store). I am working on a new app and am not sure how to appropriately solve this problem. The primary UI for the app is a Master/Detail page. I have the master detail working pretty well. However, when the app first starts, it needs to detect if the user has already been logged in. If not, I need to display a modal login view. If I use the login view as the initial page, I don’t know how to call PushAsync with a master detail page (I can only push one view model). If I display my Master Detail page first, I cannot get the view model to show the login page immediately, its like its trying to show it before the page is fully loaded. I added a button to the Main page which says Login, which when clicked will show the login page modally, once login is done, I assign the user to local storage and then pop the page. The issue now is when the page is popped, how do I update the view that presented the modal view with the new user information?

    Basically what I’m getting at is bidirectional communication between view models presented modally.

    I would appreciate any guidance on this matter! Thanks again for such a great set of articles.

    Like

  10. Hi Jonathan

    I download your great app to learn by example your wonderful UI tip on using Xamarin Forms.

    But I cannot get the MountainWeather app to run on iOS 9.0 simulator, due to an runtime exception thrown by Autofac ContainerBuilder.Build()

    Build
    ——-
    I’ve compiled the Silkweb.Mobile.MountainWeather solution in Xamarin Studio v5.9.7 on OSX. The Weather Icon Set TV-03 has been purchased and added to the iOS resource folder. The Met Office Datapoint key has been set in the MountainWeatherService class. And Newtonsoft.Json v7 had been added as a Silkweb.Mobile.Core/Reference.

    References
    – Autofac v3.5.0.0
    – Newtonsoft.Json v7
    – Xamarin.Forms.Core v1.3.1
    – Xamarin.Forms.Xaml v1.3.1

    Runtime exception
    ————————-
    When AutofacBootstrapper method Run(), calling

    line15: var container = builder.Build();

    I get a “System.ArgumentException has been thrown – The type ‘Silkweb.Mobile.MountainWeather.Services.MountainWeatherService’ is not assignable to service ‘Silkweb.Mobile.MountainWeather.Services.IMountainWeatherService’.”

    I’ve checked MountainWeatherModule and the service seems to be registered with Autofac container correctly.

    // service registration
    builder.RegisterType ()
    .As ()
    .SingleInstance();

    My background is Java, so I got a C# developers at work to have a look, but he can’t figure it out either. Have you hand this issue before Jonathan? Do you have any tips on what else i can try to the to the bottom of this?

    Many thanks in advance Jonathan
    DaveT

    Like

      1. Thanks Jonathan for your response.

        At runtime the class MountainWeatherModule method Load() is called to registers the service MountainWeatherService and the other 8 objects too.

        Note: I am replacing chevrons with [] to overcome wordpress issues.

        // service registration
        builder.RegisterType[MountainWeatherService] ()
        .As[IMountainWeatherService] ()
        .SingleInstance();

        As a test,

        1) When I removed the registration of MountainWeatherService, then the underlying AutofacBootstrapper method Run()

        line 15: var container = builder.Build();

        registers the other 8 object in the container WITHOUT throwing the exception below I got yesterday

        “System.ArgumentException has been thrown – The type ‘Silkweb.Mobile.MountainWeather.Services.MountainWeatherService’ is not assignable to service ‘Silkweb.Mobile.MountainWeather.Services.IMountainWeatherService’.”

        2) If I modify the registration of MountainWeatherService as the code below shows, where I do not include its interface As(IMountainWeatherService) in the registration

        // service registration
        builder.RegisterType[MountainWeatherService] ()
        .SingleInstance();

        then builder.Build(); register MountainWeatherService and the other 8 object in the container without an issue.

        But then later as would be expected, it throws an runtime exception in class ViewFactory method Resolve,

        line 38: viewModel = _componentContext.Resolve();

        because it cannot resolve MountainWeatherService:

        Exception: Autofac.Core.DependencyResolutionException has been thrown
        An exception was thrown while executing a resolve operation. See the InnerException for details. —> Expression of type ‘Silkweb.Mobile.MountainWeather.Services.MountainWeatherService’ cannot be used for return type ‘System.Object’

        Jonathan, are you also using Xamarin on OS-X to run your app in iOS simulator?

        I’m wondering, would the issue be with the version of Autofac. This is a tricky one. Showed it to another Senior Visual Studios C# programmer today, and he did not have a clue what was causing it either.

        I’ll try an older version of Autofac tomorrow, so see does it make a difference.

        Thanks Jonathan for your input
        Cheers
        DaveT

        Like

      2. Good news Jonathan, I got the app running in the iOS simulator. Love the custom tabs and navigator bar…sterling work.

        Workaround to get it running was to register MountainAreaViewModel with Autofac without its interface “As” IMountainAreaViewModel.

        Then I replaced any IoC reference in the code to interface IMountainWeatherService, with the implementation itself being MountainWeatherService. No more runtime exceptions, and all runs fine.

        Enjoyed part 6 of your article on the MVVC pattern. Will read part 7 to 13 tomorrow. A bit of topic, in your opinion how does the MVVC approach compare to facebook React model view messaging approach? Maybe the answer is another article in itself 😉

        Cheers Jonathan
        Dave

        Like

  11. Hi Jonathan!

    Thank you very much for the great series of post about implementing your app! I am a novice and I’ve learned pretty much from your blog about Xamarin.Forms developing. But unfortunately I can’t download any sources from your site. Is it because of some technical problems or you stopped giving the access to the sources of your application?

    Look forward to hearing from you

    Mike

    Anyway thank you!

    Like

  12. I am a developer and i can tell you that to read a tutorial without the example code eventually is worthless.
    I think that the next time you wan’t to make a tutorial or adventure with sample code make it only for this purpose and not make an app for app stores from the sample code of tutorial.

    As developers we need places in internet with good tutorials from people that want to give to community knowledge and experience.

    What a lost time this site was.

    Like

Leave a comment