Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement Prism in existing Xamarin.Forms Shared Application

I would like to know of there is a valid way to implement Prism in a existing Xamarin.Forms Shared project. I'm sure others would also like to know if they can profit from what Prism has to offer without having to convert their existing project to a PCL project. All existing examples I've found show a PCL project(probably for a good reason).

To try implementing Prism in my project I installed the Prims.Unity.Forms nuget to each platform project. I tried to inherit from PrismApplication:

public partial class App : PrismApplication 
{ }

But, this does not work. The app class does not allow me to inherit from a different base class.

Adding the following lines to my android project did not help:

protected override void OnCreate(Bundle bundle)
{      
   LoadApplication(new App(new AndroidInitializer()));
}

public class AndroidInitializer : IPlatformInitializer
{
   public void RegisterTypes(IUnityContainer container)
   { }
}

Perhaps I am missing something or trying something that structurally is not possible.

like image 503
DanielBkr Avatar asked Jul 24 '17 12:07

DanielBkr


1 Answers

Yes, it's completely possible.

First, ensure nuget packages are installed.

For example, for Prism and Unity you need:

<package id="Prism.Core" version="6.3.0" ... />
<package id="Prism.Forms" version="6.3.0" .../>
<package id="Prism.Unity.Forms" version="6.3.0" ... />
<package id="Unity" version="4.0.1" ... />

Add missing folders(just for order)

enter image description here

And move your existing page to the Views folder, but remember to adjust the namespaces or your binding just won't work.

Change application base type

Remember to change application base type in code and XAML.

using Prism.Unity;
using Xamarin.Forms;

namespace XamPrismShared
{
    public partial class App : PrismApplication
    {
        public App (IPlatformInitializer platformInitializer):base(platformInitializer)
        {                       
        }

    }
}

Set the first page and its ViewModel

Implement OnInitialized and RegisterTypes. Remember that you need to register each type you want to use with Prism as a page.

using Prism.Unity;
using Xamarin.Forms;

namespace XamPrismShared
{
    public partial class App : PrismApplication
    {
        public App (IPlatformInitializer platformInitializer):base(platformInitializer)
        {                       
        }

        protected override void OnInitialized()
        {
            InitializeComponent();
            NavigationService.NavigateAsync("MainPage");
        }

        protected override void RegisterTypes()
        {
            Container.RegisterTypeForNavigation<NavigationPage>();
            Container.RegisterTypeForNavigation<MainPage>();            
        }                
    }
}

If you have existing pages

Add ViewModelLocator.AutowireViewModel="True"to your existent views in order to allow Prism to automatically bind with their respective ViewModel.

<?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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True" x:Class="x:Class="XamPrismShared.Views.MainPage"" Title="MainPage">
   <Label Text="{Binding Title}" 
           VerticalOptions="Center" 
           HorizontalOptions="Center" />
</ContentPage>

Add the missing ViewModel

enter image description here

using Prism.Mvvm;

namespace XamPrismShared.ViewModels
{
    public class MainPageViewModel : BindableBase
    {
        public MainPageViewModel()
        {
            Title = "Hi from Prism.";
        }

        public string Title { get; set; }
    }
}

Add Platform initializers in each platform project

Add the missing platform initializers and fix Xamarin.Forms load.

  • For Android,

    using Android.App;
    using Android.Content.PM;
    using Android.OS;
    using Microsoft.Practices.Unity;
    using Prism.Unity;
    
    namespace XamPrismShared.Droid
    {
        [Activity (Label = "XamPrismShared", Icon = "@drawable/icon", Theme="@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
        public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
        {
            protected override void OnCreate (Bundle bundle)
            {
                TabLayoutResource = Resource.Layout.Tabbar;
                ToolbarResource = Resource.Layout.Toolbar; 
    
                base.OnCreate (bundle);
    
                global::Xamarin.Forms.Forms.Init (this, bundle);
                LoadApplication (new XamPrismShared.App(new AndroidPlatformInitializer()));
            }
        }
    
        public class AndroidPlatformInitializer : IPlatformInitializer
        {
            public void RegisterTypes(IUnityContainer container)
            {
    
            }
        }
    }
    
  • For iOS,

    using Foundation;
    using Microsoft.Practices.Unity;
    using Prism.Unity;
    using UIKit;
    
    namespace XamPrismShared.iOS
    {   
        [Register("AppDelegate")]
        public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
        {
            public override bool FinishedLaunching(UIApplication app, NSDictionary options)
            {
                global::Xamarin.Forms.Forms.Init ();
                LoadApplication (new XamPrismShared.App(new iOSPlatformInitializer()));
    
                return base.FinishedLaunching (app, options);
            }
        }
    
        public class iOSPlatformInitializer : IPlatformInitializer
        {
            public void RegisterTypes(IUnityContainer container)
            {
    
            }
        }
    }
    

And voilà

enter image description here

If you have any question or want to check, you can review the code in Github https://github.com/jesulink2514/Xamarin-Prism-shared-project

like image 61
Jesus Angulo Avatar answered Oct 14 '22 20:10

Jesus Angulo