Autofac.Core.DependencyResolutionException ViewModel has not been registered Autofac Xamarin.Forms - xamarin

Hey everyone I am using Autofac as my DI codebase Im following this solution Using Navigation in MasterDetailPage with Autofac and Xamarin.Forms since my Press button in tabbedPage cannot navigate to next page or link page. using Button={Binding MyNextPage} in xaml.
in that solution I am a little bit confuse about this
builder.RegisterInstance<Func<Page>>(() => ((NavigationPage)Application.Current.MainPage).CurrentPage);
As my Module I register them individually
public class ClientModule : Module
{
//Register Here for Singleton
protected override void Load(ContainerBuilder builder)
{
//RegServ Service
builder.RegisterType<PersonInfoService>().As<IPersonInfoService>().SingleInstance();
builder.RegisterType<PhoneContactService>().As<IPhoneContacts>().SingleInstance();
//RegServ View Model
builder.RegisterType<PersonViewModel>();
builder.RegisterType<PhoneContactViewModelProp>();
builder.RegisterType<LoginViewModel>();
builder.RegisterType<LoginPageViewModel>().SingleInstance();
builder.RegisterType<PersonsViewModel>().SingleInstance();
builder.RegisterType<PersonDetailViewModel>().SingleInstance();
builder.RegisterType<RegistrationViewModel>().SingleInstance();
builder.RegisterType<PhoneContactViewModel>().SingleInstance();
builder.RegisterType<MainPageViewModel>().SingleInstance();
//RegServ Views
builder.RegisterType<MainPage>().SingleInstance();
builder.RegisterType<BarcodePage>().SingleInstance();
builder.RegisterType<CustomScanPageView>().SingleInstance();
builder.RegisterType<CQRCodeOptionPage>().SingleInstance();
builder.RegisterType<PersonPageView>().SingleInstance();
builder.RegisterType<PersonDetailViewPage>().SingleInstance();
builder.RegisterType<RegistrationPage>().SingleInstance();
builder.RegisterType<ClientReadQRPage>().SingleInstance();
builder.RegisterType<LoginPage>().SingleInstance();
builder.RegisterType<PhoneBookPage>().SingleInstance();
}
}
AutofacBootstrapper.cs
namespace FormsSample.Core
{
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);
}
}
AutofacModule.cs
namespace FormsSample.Core
{
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();
}
}
}
Bootstrapper.cs
namespace FormsSample.Core
{
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<ClientModule>();
// builder.RegisterInstance<Func<Page>>(() => ((NavigationPage)Application.Current.MainPage).CurrentPage);
}
protected override void RegisterViews(IViewFactory viewFactory)
{
// register these with the view factory. ViewModel and View Page
//Autofac <object class, Func<class, >
viewFactory.Register<PersonsViewModel, PersonPageView>();
viewFactory.Register<PersonDetailViewModel, PersonDetailViewPage>();
viewFactory.Register<LoginPageViewModel, LoginPage>();
viewFactory.Register<RegistrationViewModel, RegistrationPage>();
viewFactory.Register<PhoneContactViewModel, PhoneBookPage>();
viewFactory.Register<MainPageViewModel, MainPage>();
}
protected override void ConfigureApplication(IContainer container)
{
// set main page
var viewFactory = container.Resolve<IViewFactory>();
var mainPage = viewFactory.Resolve<MainPageViewModel>();
var navigationPage = new NavigationPage(mainPage);
_application.MainPage = navigationPage;
}
}
}

You are saying
When I replace my entire module using ...
When you actually replace your whole module with the single registration the exception explains itself. Autofac can't resolve the MainPageViewModel since it has not been registered.
You have to register your module and the function that resolves the current page:
builder.RegisterModule<ClientModule>();
builder.RegisterInstance<Func<Page>>(() => ((NavigationPage)Application.Current.MainPage).CurrentPage);
Update 1
Following your last comment, I would expect the Bootstrapper to look like this:
public class Bootstrapper
{
public static void Run()
{
var builder = new ContainerBuilder();
builder.RegisterModule<ClientModule>();
builder.RegisterInstance<Func<Page>>(() => ((NavigationPage)Application.Current.MainPage).CurrentPage);
var container = builder.Build();
var page = container.Resolve<MainPage>();
YourApp.Current.MainPage = new NavigationPage(page);
}
}
Update 2
Given your example I think it should work if you do not comment out the third line in your ConfigureContainer method:
protected override void ConfigureContainer(ContainerBuilder builder)
{
base.ConfigureContainer(builder);
builder.RegisterModule<ClientModule>();
builder.RegisterInstance<Func<Page>>(() => ((NavigationPage)Application.Current.MainPage).CurrentPage);
}

Related

In a class inheriting from another, how can I set a value in the constructor of the base class?

I have this code:
using System;
using Xamarin.Forms;
namespace Test
{
public partial class ScrollHeadingView : ContentPage
{
public ScrollHeadingView()
{
// more code here
if (RightIconVisible)
{
// do some actions to add elements to each other here
var rightIconPageHeadingSvg = new PageHeadingSvg() { HorizontalOptions = LayoutOptions.StartAndExpand }
.Bind(PageHeadingSvg.SourceProperty, nameof(RightIconSource), source: this);
grid3.AddChild(rightIconPageHeadingSvg);
grid2.GestureRecognizers.Add(rightIconTap);
grid3.AddChild(rightIconPageHeadingSvg);
}
}
}
and
public partial class DecksTabPage : ScrollHeadingView
{
public DecksTabViewModel vm;
public DecksTabPage()
{
RightIconVisible = true;
BindingContext = vm = new DecksTabViewModel();
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
vm.OnAppearing();
}
}
I am setting RightIconVisible to true and want that to be reflected in ScrollHeadingView when it is constructed.
But it's not happening.
Is there a way that I can set this to happen with code in DecksTabPage?
Note that if I was using XAML I would have done this by binding to the IsVisible of a grid and then set the IsVisible to show or not show that code that has the elements. But as I am using C# I am not sure how to do this.
Constructor of parent class works before any code in constructor of child class.
To pass some value to parent class constructor, you should add a constructor parameter to it and call base constructor from child with needed value.
For example:
public partial class ScrollHeadingView : ContentPage
{
public ScrollHeadingView(bool rightIconVisible = false)
{
RightIconVisible = rightIconVisible;
if (RightIconVisible)
{
// do some actions to add elements to each other here
}
}
}
public partial class DecksTabPage : ScrollHeadingView
{
public DecksTabViewModel vm;
public DecksTabPage():base(true)
{
BindingContext = vm = new DecksTabViewModel();
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
vm.OnAppearing();
}
}
Other possibility is to remove code working with RightIconVisible from parent class constructor and put it into set of corresponding property.
public partial class ScrollHeadingView : ContentPage
{
private bool rightIconVisible;
public ScrollHeadingView()
{}
protected bool RightIconVisible
{
get => rightIconVisible;
set
{
rightIconVisible = value;
if (rightIconVisible)
{
// do some actions to add elements to each other here
}
}
}
public partial class DecksTabPage : ScrollHeadingView
{
public DecksTabViewModel vm;
public DecksTabPage()
{
RightIconVisible = true;
BindingContext = vm = new DecksTabViewModel();
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
vm.OnAppearing();
}
}

Caliburn.Micro 3.0 equivalent to Xamarin.Forms Navigation.PushModalAsync

Does Caliburn.Micro 3.0 (and Caliburn.Micro.Xamarin.Forms) implement functionality to mimic/support Navigation.PushModalAsync in Xamarin.Forms?
No. It's not build in, but its easy to enhance it. Usually, MvvM frameworks are navigating by ViewModels. Caliburn is following this pattern. So it needs some kind of navigation service. This navigationservice is responsible for creating the Views for the ViewModels and call the view framework (Xamarin.Froms in our case) specific navigation functions. NavigationPageAdapter is the thing we are searching for. Now let's enhance it.
public interface IModalNavigationService : INavigationService
{
Task NavigateModalToViewModelAsync<TViewModel>(object parameter = null, bool animated = true);
// TODO: add more functions for closing
}
public class ModalNavigationPageAdapter : NavigationPageAdapter, IModalNavigationService
{
private readonly NavigationPage _navigationPage;
public ModalNavigationPageAdapter(NavigationPage navigationPage) : base(navigationPage)
{
_navigationPage = navigationPage;
}
public async Task NavigateModalToViewModelAsync<TViewModel>(object parameter = null, bool animated = true)
{
var view = ViewLocator.LocateForModelType(typeof(TViewModel), null, null);
await PushModalAsync(view, parameter, animated);
}
private Task PushModalAsync(Element view, object parameter, bool animated)
{
var page = view as Page;
if (page == null)
throw new NotSupportedException(String.Format("{0} does not inherit from {1}.", view.GetType(), typeof(Page)));
var viewModel = ViewModelLocator.LocateForView(view);
if (viewModel != null)
{
TryInjectParameters(viewModel, parameter);
ViewModelBinder.Bind(viewModel, view, null);
}
page.Appearing += (s, e) => ActivateView(page);
page.Disappearing += (s, e) => DeactivateView(page);
return _navigationPage.Navigation.PushModalAsync(page, animated);
}
private static void DeactivateView(BindableObject view)
{
if (view == null)
return;
var deactivate = view.BindingContext as IDeactivate;
if (deactivate != null)
{
deactivate.Deactivate(false);
}
}
private static void ActivateView(BindableObject view)
{
if (view == null)
return;
var activator = view.BindingContext as IActivate;
if (activator != null)
{
activator.Activate();
}
}
}
We just declared the interface IModalNavigationService that extends INavigationService and implement it in our ModalNavigationPageAdapter. Unfortunately Caliburn made alot of functions private, so we have to copy them over to our inherited version.
In caliburn you can navigate via navigationservice.For<VM>().Navigate(). We want to follow this style, so we have to implement something like navigationservice.ModalFor<VM>().Navigate() which we do in an extension method.
public static class ModalNavigationExtensions
{
public static ModalNavigateHelper<TViewModel> ModalFor<TViewModel>(this IModalNavigationService navigationService)
{
return new ModalNavigateHelper<TViewModel>().AttachTo(navigationService);
}
}
This method returns a ModalNavigateHelperthat simplifies the usage of our navigation service (similar to Caliburn's NavigateHelper). It's nearly a copy, but for the IModalNavigationService.
public class ModalNavigateHelper<TViewModel>
{
readonly Dictionary<string, object> parameters = new Dictionary<string, object>();
IModalNavigationService navigationService;
public ModalNavigateHelper<TViewModel> WithParam<TValue>(Expression<Func<TViewModel, TValue>> property, TValue value)
{
if (value is ValueType || !ReferenceEquals(null, value))
{
parameters[property.GetMemberInfo().Name] = value;
}
return this;
}
public ModalNavigateHelper<TViewModel> AttachTo(IModalNavigationService navigationService)
{
this.navigationService = navigationService;
return this;
}
public void Navigate(bool animated = true)
{
if (navigationService == null)
{
throw new InvalidOperationException("Cannot navigate without attaching an INavigationService. Call AttachTo first.");
}
navigationService.NavigateModalToViewModelAsync<TViewModel>(parameters, animated);
}
}
Last but not least, we have to use our shiny new navigation service instead of the old one. The App class is registering the NavigationPageAdapter for the INavigationService as singleton in PrepareViewFirst. We have to change it as follows
public class App : FormsApplication
{
private readonly SimpleContainer container;
public App(SimpleContainer container)
{
this.container = container;
container
.PerRequest<LoginViewModel>()
.PerRequest<FeaturesViewModel>();
Initialize();
DisplayRootView<LoginView>();
}
protected override void PrepareViewFirst(NavigationPage navigationPage)
{
var navigationService = new ModalNavigationPageAdapter(navigationPage);
container.Instance<INavigationService>(navigationService);
container.Instance<IModalNavigationService>(navigationService);
}
}
We are registering our navigation service for INavigationService and IModalNavigationService.
As you can see in the comment, you have to implement close functions that call PopModalAsync by yourself.

MvvmCross cannot find override method for mapping view model to view

Has the Setup class methods or hierarchy changed? I cannot seem to find a method called GetViewModelViewLookup to override in the Setup class
I am trying to map a view to a different view model. I am using MvvmCross 3.5.1
I am trying the following
protected override IDictionary<Type, Type> GetViewModelViewLookup()
but it tells me there is not a method named this to override. I am trying to follow the example on the old MvvmCross blog link
Any ideas?
Update * it looks as if the base class used to be MvxBaseSetup which contained GetViewModelToViewLookup, but now it is just MvxSetup which does not contain it.
So how do I override the viewmodel to view mapping now?
If you just want to change the naming scheme, the function to overwrite is CreateViewToViewModelNaming
public class Setup : MvxAndroidSetup
{
public Setup(Context applicationContext) : base(applicationContext)
{
}
protected override IMvxNameMapping CreateViewToViewModelNaming()
{
return new ReverseViewModelNaming();
}
protected override IMvxApplication CreateApp()
{
return new Core.App();
}
protected override IMvxTrace CreateDebugTrace()
{
return new DebugTrace();
}
}
class ReverseViewModelNaming : IMvxNameMapping
{
public string Map(string inputName)
{
// MyView is presented by the view model named weiVyM (how useful :P)
return string.Join("", inputName.Reverse());
}
}
If you want to change the mapping, the function to overwrite is InitializeViewLookup. If you just want to add some extra mappings, call base.InitializeViewLookup().
public class Setup : MvxAndroidSetup
{
public Setup(Context applicationContext) : base(applicationContext)
{
}
protected override void InitializeViewLookup()
{
var registry = new Dictionary<Type, Type>()
{
{ typeof(FirstViewModel), typeof(FirstActivity) },
{ typeof(HomeViewModel), typeof(HomeActivity) } ,
{ typeof(DetailViewModel), typeof(DetailActivity) },
{ typeof(UploadViewModel), typeof(UploadActivity) }
};
var container = Cirrious.CrossCore.Mvx.Resolve<IMvxViewsContainer>();
container.AddAll(registry);
}
protected override IMvxApplication CreateApp()
{
return new Core.App();
}
protected override IMvxTrace CreateDebugTrace()
{
return new DebugTrace();
}
}

SignalR + Dependency Injection Questions

I am using SignalR in my MVC3 application, and since I have implemented StructureMap Dependency Injection on my controllers I would like to do the same in my hub, but I can't seem to get it working.
Please tell me what's wrong with my codes below:
SignalRSmDependencyResolver.cs
public class SignalRSmDependencyResolver : DefaultDependencyResolver
{
private IContainer _container;
public SignalRSmDependencyResolver(IContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
object service = null;
if (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
{
// Concrete type resolution
service = _container.GetInstance(serviceType);
}
else
{
// Other type resolution with base fallback
service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
}
return service;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var objects = _container.GetAllInstances(serviceType).Cast<object>();
objects.Concat(base.GetServices(serviceType));
return objects;
}
}
SignalRExtensionsRegistry.cs
public class SignalRExtensionsRegistry : Registry
{
public SignalRExtensionsRegistry()
{
For<IDependencyResolver>().Add<SignalRSmDependencyResolver>();
}
}
IoC.cs
public static class IoC {
public static IContainer Initialize() {
var container = BootStrapper.Initialize();
container.Configure(x =>
{
x.For<IControllerActivator>().Singleton().Use<StructureMapControllerActivator>();
});
return container;
}
}
public class StructureMapControllerActivator : IControllerActivator {
public StructureMapControllerActivator(IContainer container) {
_container = container;
}
private IContainer _container;
public IController Create(RequestContext requestContext, Type controllerType) {
IController controller = DependencyResolver.Current.GetService(controllerType) as IController;
return controller;
}
}
AppStart_Structuremap.cs
[assembly: WebActivator.PreApplicationStartMethod(typeof(StoreUI.AppStart_Structuremap), "Start")]
namespace MyNameSpace {
public static class AppStart_Structuremap {
public static void Start() {
var container = (IContainer) IoC.Initialize();
DependencyResolver.SetResolver(new StructureMapDependenceyResolver(container));
AspNetHost.SetResolver(new StructureMapDependencyResolver(container));
}
}
}
NotificationsHub.cs
[HubName("notificationsHub")]
public class NotificationsHub : Hub
{
#region Declarations
private readonly IUserService userService;
#endregion
#region Constructor
public NotificationsHub(IUserService userService)
{
this.userService = userService;
}
#endregion
public void updateServer(string message)
{
Clients.updateClient(message);
}
}
Thanks
Getting Structuremap into SignalR is actually pretty easy. First you want to create your own resolver:
StructureMap Resolver
Usings:
using SignalR.Infrastructure;
using StructureMap;
Class:
public class StructureMapResolver : DefaultDependencyResolver
{
private IContainer _container;
public StructureMapResolver(IContainer container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
object service = null;
if (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
{
// Concrete type resolution
service = _container.GetInstance(serviceType);
}
else
{
// Other type resolution with base fallback
service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
}
return service;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
var objects = _container.GetAllInstances(serviceType).Cast<object>();
return objects.Concat(base.GetServices(serviceType));
}
}
The idea here is to try and use your container to resolve the dependencies, if you do not have the dependency wired up, pass it through to the default resolver. This way you don't have to worry about all of the other dependencies in SignalR and can focus only on the stuff you want to inject into (Hubs, ConnectionIdFactory, MessageBus, etc.).
Bindings for Resolver and Hub
Next you will want to register this in your container (i like using registries):
Usings:
using SignalR.Infrastructure;
using StructureMap.Configuration.DSL;
Class:
public class ExtensionsRegistry : Registry
{
public ExtensionsRegistry()
{
For<IDependencyResolver>().Add<StructureMapResolver>();
}
}
Resolver Replacement
Finally you will want to tell SignalR to use your resolver instead of the default:
Global::Application_Start or WebActivator::Pre_Start
Usings:
using SignalR.Hosting.AspNet;
using SignalR.Infrastructure;
Application_Start:
// Make sure you build up the container first
AspNetHost.SetResolver(StructureMap.ObjectFactory.GetInstance<IDependencyResolver>());
Silly Hub with injected dependencies
Now you can just inject any dependencies your container knows about into the hubs themselves:
[HubName("defaultHub")]
public class DefaultHub : Hub, IDisconnect
{
private readonly IRepository _repo;
public DefaultHub(IRepository repo)
{
_repo = repo;
}
public void Connect()
{
Caller.setUser(Context.ConnectionId);
Clients.addMessage(string.Format("{0} has connected", Context.ConnectionId));
}
public void MessageSender(string message)
{
Caller.addMessage(_repo.RepositoryMessage());
Clients.addMessage(message);
}
public Task Disconnect()
{
var clientId = this.Context.ConnectionId;
return Task.Factory.StartNew(() => { Clients.addMessage(string.Format("{0} has disconnected", clientId)); });
}
}
Have you followed the instructions here:- https://github.com/SignalR/SignalR/wiki/Extensibility ?
You'll need to use AspNetHost.SetResolver.
I know this is an old thread, but for those who are wondering where is the AspNetHost.SetResolver in the newer version of signalR, you can use this in the App_Start StructuremapMvc.cs:
public static void Start() {
IContainer container = IoC.Initialize();
GlobalHost.DependencyResolver = new SignalRSmDependencyResolver(container); // for signalR
DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(container);
}
Add something like this to a file in your App_Start folder. This code snippet is for Ninject, so just replace AspNetHost.SetResolver()
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Ninject;
using SignalR.Hosting.AspNet;
using SignalR.Infrastructure;
using SignalR.Ninject;
using Web.Models;
[assembly: WebActivator.PreApplicationStartMethod(typeof(Web.App_Start.NinjectSignalR), "Start")]
namespace Web.App_Start
{
public static class NinjectSignalR
{
public static void Start()
{
IKernel kernel = CreateKernel();
// switch this line to the structuremap resolver
AspNetHost.SetResolver(new NinjectDependencyResolver(kernel));
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
// add your services here
//kernel.Bind<IRepository>().To<Repository>();
}
}
}

NavigationService throws NullReferenceException

Using MVVM Light, I'm trying to develop a rather simple WP7 application. I've run into a problem using the navigation service. I can navigate to a page, but after pressing the back button I can't navigate to the same page again. NavigationService throws a NullReferenceException.
I have implemented my navigation using Messaging from the GalaSoft.MvvmLight.Messaging namespace. All my views inherits from a customized PhoneApplicationPage base class that registrers a listener on "NavigationRequest":
public class PhoneApplicationPage : Microsoft.Phone.Controls.PhoneApplicationPage
{
public PhoneApplicationPage() : base()
{
Messenger.Default.Register<Uri>(this, "NavigationRequest", (uri) => NavigationService.Navigate(uri));
}
}
From my view models I post Uri's to this listener:
SendNavigationRequestMessage(new Uri("/View/AppSettingsView.xaml", UriKind.Relative));
Like i said, this works except when navigating after pressing the Back button.
Why is this and how can I solve it?
Is there a better way to implement navigation using MVVM Light?
I'm using MVVM Light as well. I have a class called PageConductor, which is based on what John Papa (Silverlight MVP) from Microsoft uses. Here's the PageConductor Service I use
public class PageConductor : IPageConductor
{
protected Frame RootFrame { get; set; }
public PageConductor()
{
Messenger.Default.Register<Messages.FrameMessage>(this, OnReceiveFrameMessage);
}
public void DisplayError(string origin, Exception e, string details)
{
string description = string.Format("Error occured in {0}. {1} {2}", origin, details, e.Message);
var error = new Model.Error() { Description = description, Title = "Error Occurred" };
Messenger.Default.Send(new Messages.ErrorMessage() { Error = error });
}
public void DisplayError(string origin, Exception e)
{
DisplayError(origin, e, string.Empty);
}
private void OnReceiveFrameMessage(Messages.FrameMessage msg)
{
RootFrame = msg.RootFrame;
}
private void Go(string path, string sender)
{
RootFrame.Navigate(new Uri(path, UriKind.Relative));
}
public void GoBack()
{
RootFrame.GoBack();
}
}
In my MainPage.xaml.cs constructor, I have this, which creates an instance of my ContentFrame in my PageConductor service.:
Messenger.Default.Send(new Messages.FrameMessage() { RootFrame = ContentFrame });
I then use dependency injection to instantiate an instance of my PageConductor Service into my MainPage ViewModel. Here is my MainViewModel class:
protected Services.IPageConductor PageConductor { get; set; }
public RelayCommand<string> NavigateCommand { get; set; }
public MainViewModel(Services.IPageConductor pageConductor)
{
PageConductor = pageConductor;
RegisterCommands();
}
private void RegisterCommands()
{
NavigateCommand = new RelayCommand<string>(
(source) => OnNavigate(source));
}
private void OnNavigate(string sender)
{
PageConductor.GoToView(sender, "main");
}
Notice the instance of my PageConductorService as a parameter in my MainViewModel constructor method. I pass this in via my ViewModelLocator:
private readonly TSMVVM.Services.ServiceProviderBase _sp;
public ViewModelLocator()
{
_sp = Services.ServiceProviderBase.Instance;
CreateMain(_sp);
}
#region MainPageViewModel
public static MainViewModel MainStatic
{
get
{
Services.ServiceProviderBase SP = Services.ServiceProviderBase.Instance;
if (_main == null)
{
CreateMain(SP);
}
return _main;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return MainStatic;
}
}
public static void ClearMain()
{
_main.Cleanup();
_main = null;
}
public static void CreateMain(Services.ServiceProviderBase SP)
{
if (_main == null)
{
_main = new MainViewModel(SP.PageConductor);
}
}
#endregion
For further reference, my Messages.FrameMessage class is simply:
internal class FrameMessage
{
public Frame RootFrame { get; set; }
}
I've had no issues with forward/back buttons.

Resources