简体   繁体   中英

Caliburn.Micro Xamarin.Forms ViewModel does not initialize

I created a new Xamarin.Forms project and I'm having issues with the view model initializing. Nothing happens. I'm using the samples from the Features . I modified the sample code to the following:

public FormsApp(SimpleContainer container)
    {
       //...

        DisplayRootView<ConductorView>();
    } 

This works as expected, but on my project it simply does not work.

I am using .NET Standard 1.5 (not sure if this is causing the issue). In any case here is my code

App.cs:

using System;
using Caliburn.Micro;
using Caliburn.Micro.Xamarin.Forms;
using UniversalSqlManager.ViewModels;
using Xamarin.Forms;
using INavigationService = Caliburn.Micro.Xamarin.Forms.INavigationService;
using UniversalSqlManager.Views;
namespace UniversalSqlManager
{
    public class App : FormsApplication
    {
        private readonly SimpleContainer container;

        public App(SimpleContainer container)
        {
            this.container = container;

            container
                .PerRequest<ShellViewModel>();

            this.DisplayRootView<ShellView>();
        }

        protected override void PrepareViewFirst(NavigationPage navigationPage)
        {
            container.Instance<INavigationService>(new NavigationPageAdapter(navigationPage));
        }
    }
}

ShellView.xaml:

    <?xml version="1.0" encoding="utf-8"?>
    <TabbedPage 
        xmlns="http://xamarin.com/schemas/2014/forms" 
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
        xmlns:local="clr-namespace:UniversalSqlManager" 
        x:Class="UniversalSqlManager.Views.ShellView"
        xmlns:cm="clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms"
        ItemsSource="{Binding Items}"
        SelectedItem="{Binding ActiveItem, Mode=TwoWay}"
        Title="Universal SQL Manager">
        <TabbedPage.ItemTemplate>
            <DataTemplate>
                <ContentPage Title="{Binding DisplayName}" cm:View.Model="{Binding}" />
            </DataTemplate>
        </TabbedPage.ItemTemplate>
    </TabbedPage>

ShellView.xaml.cs:

    using Xamarin.Forms;

    namespace UniversalSqlManager.Views
    {
        public partial class ShellView
        {
            public ShellView()
            {
                InitializeComponent();
            }
        }
    }

ShellViewModel.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Caliburn.Micro;
    using Caliburn.Micro.Xamarin.Forms;
    using UniversalSqlManager.ViewModels.Interfaces;

    namespace UniversalSqlManager.ViewModels
    {
        public class ShellViewModel : Conductor<ITabItem>.Collection.OneActive
        {
            protected override void OnInitialize()
            {
                //both view models implement ITabItem (which has no methods) and inherit form Screen
                Items.Add(new ServersViewModel());
                Items.Add(new SettingsViewModel());

                ActivateItem(Items[0]);
            }
        }
    }

I'll show iOS as that's the first platform I'm testing on

AppDelegate.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Caliburn.Micro;

    using Foundation;
    using UIKit;

    namespace UniversalSqlManager.iOS
    {
        [Register(nameof(AppDelegate))]
        public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
        {
            private readonly CaliburnAppDelegate appDelegate = new CaliburnAppDelegate();

            public override bool FinishedLaunching(UIApplication app, NSDictionary options)
            {
                global::Xamarin.Forms.Forms.Init();

                LoadApplication(IoC.Get<App>());

                return base.FinishedLaunching(app, options);
            }
        }
    }

CaliburnAppdelegate.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using Caliburn.Micro;
    using UniversalSqlManager.ViewModels.Interfaces;

    namespace UniversalSqlManager.iOS
    {
        public class CaliburnAppDelegate : CaliburnApplicationDelegate
        {
            private SimpleContainer container;

            public CaliburnAppDelegate()
            {
                Initialize();
            }

            protected override void Configure()
            {
                container = new SimpleContainer();
                container.Instance(container);
                container.Singleton<App>();
                container.Singleton<IEventAggregator, EventAggregator>();
            }

            protected override void BuildUp(object instance)
            {
                container.BuildUp(instance);
            }

            protected override IEnumerable<object> GetAllInstances(Type service)
            {
                return container.GetAllInstances(service);
            }

            protected override object GetInstance(Type service, string key)
            {
                return container.GetInstance(service, key);
            }
        }
    }

So when I run this the ShellView UI shows up, but the ShellViewModel does not get initialized and I get no tabs. Even if I switch to SettingsView or ServersView, the corresponding view models never get initialized. What am I doing wrong? This is my first time with Caliburn Micro on Xamarin.Forms. I've used WPF in the past without issues. Just the documentation is confusing, because it just seems like we have these examples to go by and some blogs that aren't as detailed as the WPF documentation. Any help would be appreciated. I can post my csproj and project.json if that will help too, but I'm hesitant to switch the project type as it was a pain to set that up. I guess another alternative would be to create a new project with a PCL and see if that works? Running out of ideas. Any help is appreciated!

So it turns out the problem was that I was not telling the framework which assemblies to use. The Features samples don't use libraries for the share code. So I added this to CaliburnAppDelegate.cs and to Application.cs to iOS and Android respectively:

protected override IEnumerable<Assembly> SelectAssemblies()
{
    return this.GetAssemblies();
}

This is an extension I created in my class library:

public static class Bootstrapper
{
//...

public static IEnumerable<Assembly> GetAssemblies(this object o)
    {
        IEnumerable<Assembly> assemblies =
        new[]
        {
            o.GetType().GetTypeInfo().Assembly,
            typeof(ShellViewModel).GetTypeInfo().Assembly
        };
        return assemblies;
    }
//...
}

and this solves the problem. I hope this help someone else who is having issues hooking up the sample using a class library. By the way I figured this out when comparing with the setup samples.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM