Property Injection (setter injection) Prism for Xamarin.Forms - c#

Is the setter injection supported in the Xamarin.forms?
I have a service injected in the bootstrapper like this
Container.RegisterType<ICommonService, CommonService>();
And inside a viewmodel, I want to have an instance injected to a property like this
[Dependency]
public ICommonService CommonService { get; set; }
But in the runtime, the property CommonService is always null.
The attribute I used is the Microsoft.Practices.Unity.DependencyAttribute, not Xamarin.Forms.DependencyAttribute
If I inject inside the constructor, it works
public LandingPageViewModel(INavigationService navigationService, ICommonService commonService)
Edited: added code snippet
public class Bootstrapper : UnityBootstrapper
{
protected override Page CreateMainPage()
{
try
{
return Container.Resolve<Views.LandingPage>();
}
catch (Exception exception)
{
//TODO: intent to get exception info
throw;
}
}
protected override void RegisterTypes()
{
DependencyResolver.Instance.Initialize(Container);
this.RegisterViews();
this.RegisterServices();
this.RegisterSingleton();
}
private void RegisterViews()
{
Container.RegisterTypeForNavigation<LandingPage>();
Container.RegisterTypeForNavigation<Page1>();
}
private void RegisterServices()
{
Container.RegisterType<ICommonService, CommonService>();
}
private void RegisterSingleton()
{
}
}
public partial class App : Application
{
public App()
{
InitializeComponent();
var bootstrapper = new Bootstrapper();
bootstrapper.Run(this);
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}

Hmm they removed the DependencyAttribute injection feature since Prism 7.0, I think we should register it manually. (your code snippet should work)
Look: https://brianlagunas.com/whats-new-in-prism-for-xamarin-forms-7-0/

Related

Use Zenject FromSubContainerResolve on ProjectContext to SceneContext

I have a Unity + Zenject setup with a ProjectInstaller with some global dependencies that adhere to a "modal" interface, e.g.,
public class ProjectInstaller : MonoInstaller {
public override void InstallBindings() {
Container.Bind<ModalManager>().AsSingle();
Container.Bind<Modal>().To<DialogManager>().AsSingle();
}
}
Some modals are only relevant to certain scenes, so I bind those in the SceneInstaller:
public class SceneInstaller : MonoInstaller {
public override void InstallBindings() {
Container.BindInterfacesAndSelfTo<InventoryManager>()
.FromComponentInNewPrefab(InventoryPrefab)
.AsSingle()
}
}
I want to manage all modals from the single ModalManager, defined at the project scope. So it has a List<Modal> binding:
public class ModalManager : MonoBehaviour {
[Inject]
protected List<Modal> _modals;
}
When I run this, the ModalManager only gets a single modal: the one defined in the project scope. In my understanding the SceneContext is a subcontainer of the ProjectContext. So I should be able to use FromSubContainerResolve in the ProjectInstaller to bind items in the child scene, perhaps by adding a line like:
// ProjectInstaller.cs
public override void InstallBindings() {
// ...
Container.Bind<Modal>().To<InventoryManager>().FromSubContainerResolve();
}
But I'm not sure which of the eleventy FromSubContainerResolve methods make sense for this case. They all seem pertinent to prefabs with a game object context, not for use from within the ProjectContext.
Does this use case make sense? Is there an easier or better way?
The problem is that that ModalManager can only be injected with dependencies that are added directly to ProjectContext. For these kinds of problems I recommend using the following pattern:
public interface IModal
{
}
public class ModalManager
{
private readonly List<IModal> _modals = new List<IModal>();
public IReadOnlyList<IModal> Modals
{
get { return _modals; }
}
public void AddModal(IModal modal)
{
_modals.Add(modal);
}
public bool RemoveModal(IModal modal)
{
return _modals.Remove(modal);
}
}
public class ModalRegisterHandler : IInitializable, IDisposable
{
private readonly List<IModal> _modals;
private readonly ModalManager _modalManager;
public ModalRegisterHandler(
// We need to use InjectSources.Local here, otherwise we will
// add any project context modals again in each scene
[Inject(Source = InjectSources.Local)]
List<IModal> modals, ModalManager modalManager)
{
_modals = modals;
_modalManager = modalManager;
}
public void Initialize()
{
foreach (var modal in _modals)
{
_modalManager.AddModal(modal);
}
}
public void Dispose()
{
// We don't want ModalManager to retain references to Modals defined in unloaded scenes
// (dispose is executed on scene unload)
foreach (var modal in _modals)
{
_modalManager.RemoveModal(modal);
}
}
}
public class SceneInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<IModal>().To<FooModal>();
Container.Bind<IModal>().To<BarModal>();
}
}
public class ProjectInstaller : MonoInstaller
{
public override void InstallBindings()
{
// We use CopyIntoDirectSubContainers so that ModalRegisterHandler gets automatically added to every
// scene context
Container.BindInterfacesTo<ModalRegisterHandler>().AsSingle().CopyIntoDirectSubContainers();
Container.Bind<ModalManager>().AsSingle();
Container.Bind<IModal>().To<QuxModal>();
Container.Bind<IModal>().To<FizzModal>();
}
}

Injection of Repository into ShellViewModel, via Bootstrapper OnStartUp

I'm stuck!
I'm using Caliburn.micro to take away some of the pain implementing MVVM in a WPF application.
Currently I only have a single View / ViewModel, but in the future there could be several ViewModels. The current ViewModel is using a Repository to populate a list of objects:
public class ShellViewModel : Screen
{
private IMyObjectRepository<IMyObject> _myObjectsRepo = null;
private BindableCollection<MyObject> _myObjects;
private string _connString;
/// <summary>
/// constructor
/// </summary>
public ShellViewModel()
{
//call the method which sets up the repository
GetMyObjectsRepository();
//following three lines cast the list from type IReport to type Report
var IMyObjects= _myObjectsRepo.GetAllIMyObjects();
var myObjects = IMyObjects.OfType<MyObject>().ToList();
MyObjects = new BindableCollection<MyObject>(myObjects );
}
private void GetMyObjectsRepository()
{
_connString = ConfigurationManager.ConnectionStrings["xxx"].ConnectionString;
_myObjectRepo = MyObjectRepositoryFactory.InstantiateRepo(_connString);
}
The above smells like a future problem - if I create a different ViewModel which has its own attribute of BindableCollection<MyObject> _myObjects; then the two collections, of the same objects, could quickly have different states i.e. ObjectX in the first ViewModel might change its name attribute, but ObjectX still has its original name in the second ViewModel.
I was thinking I could inject this list of <MyObject> into the ViewModel when it is constructed - should I do this in Bootstrapper.cs? (I'd rather avoid full blown DI as this is a small project)
Currently Bootstrapper.cs looks like the following - how do I move some of the logic in the above code snippet into here? Does it go in the OnStartUp event method? If so then how?
using Caliburn.Micro;
using Prototype_WPF.ViewModels;
using System.Windows;
namespace Prototype_WPF
{
public class Bootstrapper: BootstrapperBase
{
public Bootstrapper()
{
Initialize();
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
}
}
}
You could use the Handler method to register factory methods for your view models in the bootstrapper:
public class Bootstrapper : BootstrapperBase
{
private readonly BindableCollection<MyObject> _myObjects = new BindableCollection<MyObject>();
private SimpleContainer container;
public Bootstrapper()
{
Initialize();
}
protected override void Configure()
{
container = new SimpleContainer();
container.Singleton<IWindowManager, WindowManager>();
container.Handler<ShellViewModel>(_ => new ShellViewModel(_myObjects));
container.Handler<SomeOtherViewModel>(_ => new SomeOtherViewModel(_myObjects));
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor(typeof(ShellViewModel));
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}
You can create a separate component for retrieving your objects, something like IMyObjectService and implement it.
public interface IMyObjectService
{
IList<MyObject> GetMyObjects();
}
Than create an overload of Configure method in Bootstrapper and register an implementation, something like that:
protected override void Configure()
{
container = new SimpleContainer();
container.Singleton<IMyObjectService, MyObjectService>();
//other registrations
container.PerRequest<ShellViewModel>();
}
And finally use a constructor injection for any ViewModel to inject and use this service. The Caliburn.Micro documentation already has some examples
You can 'Register' the service and 'Register' every class like below
protected override void Configure()
{
container = new SimpleContainer();
container.Instance(container);
container
.Singleton<IMyObjectService, MyObjectService>();
//Register all ViewModel classes
GetType().Assembly.GetTypes()
.Where(type => type.IsClass)
.Where(type => type.Name.EndsWith("ViewModel"))
.ToList()
.ForEach(viewModleType => container.RegisterPerRequest(
viewModleType, viewModleType.ToString(), viewModleType));
}

Initialize Shell with ViewModel after all modules loaded in Prism 6

The ViewModel (set via AutoWireViewModel="True") of my Shell / MainWindow requests a dependency which gets loaded in a module at startup using the ConfigurationModuleCatalog.
Because the Shell is initialzed before the modules, the DI container obviously can't resolve it, so the application crashes.
public class MainWindowViewModel : BindableBase
{
// Cannot resolve IService
public MainWindowViewModel(IService service)
{
}
}
I already tried the two approaches of this post, but both didn't worked.
I tried it this way:
public interface IShellService
{
int NumberOfLoadedModules { get; }
void FlagModuleAsLoaded();
}
public class ShellService : IShellService
{
private readonly IModuleCatalog _moduleCatalog;
public ShellService(IModuleCatalog moduleCatalog)
{
_moduleCatalog = moduleCatalog;
}
public int NumberOfLoadedModules { get; private set; }
public void FlagModuleAsLoaded()
{
NumberOfLoadedModules++;
if (NumberOfLoadedModules != _moduleCatalog.Modules.Count())
return;
InitializeShell();
}
private static void InitializeShell()
{
Application.Current.MainWindow.Show();
}
}
internal class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return null;
}
protected override void InitializeShell()
{
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
Container.RegisterInstance<IShellService>(new ShellService(ModuleCatalog), new ContainerControlledLifetimeManager());
}
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
}
Usage
public abstract class ModuleBase : IModule
{
private readonly IShellService _shellService;
protected ModuleBase(IShellService shellService)
{
_shellService = shellService;
}
public void Initialize()
{
InitializeInternal();
FlagAsLoaded();
}
public abstract void InitializeInternal();
public void FlagAsLoaded()
{
_shellService.FlagModuleAsLoaded();
}
}
public class FooModule : ModuleBase
{
IUnityContainer _container;
public MusicUIModule(IUnityContainer container, IShellService shellService) : base(shellService)
{
_container = container;
}
public override void InitializeInternal()
{
_container.RegisterType<IService, Service>();
}
}
It starts counting the modules and then the application crashes because of the same reason.
If the approach above isn't fitting for my purpose, how could that problem be solved?
Thanks!
I tried to implement Haukinger's suggestion and did it this way which works just fine:
// Factory --------------------------------------------------------
public interface IDependencyFactory
{
IService GetService();
}
public class DependencyFactory : IDependencyFactory
{
private readonly IUnityContainer _container;
public DependencyFactory(IUnityContainer container)
{
_container = container;
}
public IService GetService()
{
return _container.Resolve<IService>();
}
}
// PubSubEvent ------------------------------------------------------
public class AllModulesLoaded : PubSubEvent
{
}
// Bootstrapper -----------------------------------------------------
internal class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow.Show();
}
protected override void InitializeModules()
{
base.InitializeModules();
// Publishing event to tell subscribers that the modules are loaded
var eventAggregator = Container.Resolve<IEventAggregator>();
eventAggregator?.GetEvent<AllModulesLoaded>().Publish();
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
// ...
Container.RegisterType<IDependencyFactory, DependencyFactory>();
}
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
}
// ViewModel ---------------------------------------------------------
public class MainWindowViewModel : BindableBase
{
private IService _service;
private readonly IEventAggregator _eventAggregator;
private readonly IDependencyFactory _dependencyFactory;
public MainWindowViewModel(IEventAggregator eventAggregator, IDependencyFactory dependencyFactory)
{
_eventAggregator = eventAggregator;
_dependencyFactory = dependencyFactory;
_eventAggregator.GetEvent<AllModulesLoaded>().Subscribe(OnAllModulesLoaded);
}
private void OnAllModulesLoaded()
{
var service = _dependencyFactory.GetService();
if (service != null)
_service = service ;
_eventAggregator.GetEvent<AllModulesLoaded>().Unsubscribe(OnAllModulesLoaded);
}
}
I'd hide the dependency of the shell behind a factory/provider and then create/fetch it when the last module is loaded. Your shell's view model subscribes to a AllModulesLoaded event that's fired from your bootstrapper's InitializeModules when base.InitializeModules returns to get notified that the dependency is available. Or the factory/provider subscribes to the event and the shell polls it, depending on how you want to use the dependency.

Seemann's Dependency Injection, "Three Calls Pattern" vs Service Locator Anit-Pattern

I have created a WinForms MVC application using Dependency Injection (DI) and Ninject as the DI Container. The basic architecture is as follows
Program.cs (the main entry point of the WinForms application):
static class Program
{
[STAThread]
static void Main()
{
...
CompositionRoot.Initialize(new DependencyModule());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(CompositionRoot.Resolve<ApplicationShellView>());
}
}
DependencyModule.cs
public class DependencyModule : NinjectModule
{
public override void Load()
{
Bind<IApplicationShellView>().To<ApplicationShellView>();
Bind<IDocumentController>().To<SpreadsheetController>();
Bind<ISpreadsheetView>().To<SpreadsheetView>();
}
}
CompositionRoot.cs
public class CompositionRoot
{
private static IKernel ninjectKernel;
public static void Initialize(INinjectModule module)
{
ninjectKernel = new StandardKernel(module);
}
public static T Resolve<T>()
{
return ninjectKernel.Get<T>();
}
public static IEnumerable<T> ResolveAll<T>()
{
return ninjectKernel.GetAll<T>();
}
}
ApplicationShellView.cs (the main form of the application)
public partial class ApplicationShellView : C1RibbonForm, IApplicationShellView
{
private ApplicationShellController controller;
public ApplicationShellView()
{
this.controller = new ApplicationShellController(this);
InitializeComponent();
}
public void InitializeView()
{
dockPanel.Extender.FloatWindowFactory = new CustomFloatWindowFactory();
dockPanel.Theme = vS2012LightTheme;
}
private void ribbonButtonTest_Click(object sender, EventArgs e)
{
controller.OpenNewSpreadsheet();
}
public DockPanel DockPanel
{
get { return dockPanel; }
}
}
where
public interface IApplicationShellView
{
void InitializeView();
DockPanel DockPanel { get; }
}
ApplicationShellController.cs
public class ApplicationShellController
{
private IApplicationShellView shellView;
public ApplicationShellController(IApplicationShellView view)
{
this.shellView = view;
}
public void OpenNewSpreadsheet(DockState dockState = DockState.Document)
{
SpreadsheetController controller = (SpreadsheetController)GetDocumentController("new.xlsx");
SpreadsheetView view = (SpreadsheetView)controller.New("new.xlsx");
view.Show(shellView.DockPanel, dockState);
}
private IDocumentController GetDocumentController(string path)
{
return CompositionRoot.ResolveAll<IDocumentController>()
.SingleOrDefault(provider => provider.Handles(path));
}
public IApplicationShellView ShellView { get { return shellView; } }
}
SpreadsheetController.cs
public class SpreadsheetController : IDocumentController
{
private ISpreadsheetView view;
public SpreadsheetController(ISpreadsheetView view)
{
this.view = view;
this.view.SetController(this);
}
public bool Handles(string path)
{
string extension = Path.GetExtension(path);
if (!String.IsNullOrEmpty(extension))
{
if (FileTypes.Any(ft => ft.FileExtension.CompareNoCase(extension)))
return true;
}
return false;
}
public void SetViewActive(bool isActive)
{
((SpreadsheetView)view).ShowIcon = isActive;
}
public IDocumentView New(string fileName)
{
// Opens a new file correctly.
}
public IDocumentView Open(string path)
{
// Opens an Excel file correctly.
}
public IEnumerable<DocumentFileType> FileTypes
{
get
{
return new List<DocumentFileType>()
{
new DocumentFileType("CSV", ".csv" ),
new DocumentFileType("Excel", ".xls"),
new DocumentFileType("Excel10", ".xlsx")
};
}
}
}
where the implemented interface is
public interface IDocumentController
{
bool Handles(string path);
void SetViewActive(bool isActive);
IDocumentView New(string fileName);
IDocumentView Open(string path);
IEnumerable<DocumentFileType> FileTypes { get; }
}
Now the view ascociated with this controller is
public partial class SpreadsheetView : DockContent, ISpreadsheetView
{
private IDocumentController controller;
public SpreadsheetView()
{
InitializeComponent();
}
private void SpreadsheetView_Activated(object sender, EventArgs e)
{
controller.SetViewActive(true);
}
private void SpreadsheetView_Deactivate(object sender, EventArgs e)
{
controller.SetViewActive(false);
}
public void SetController(IDocumentController controller)
{
this.controller = controller;
Log.Trace("SpreadsheetView.SetController(): Controller set successfully");
}
public string DisplayName
{
get { return Text; }
set { Text = value; }
}
public WorkbookView WorkbookView
{
get { return workbookView; }
set { workbookView = value; }
}
...
}
Finally the view interfaces are
public interface ISpreadsheetView : IDocumentView
{
WorkbookView WorkbookView { get; set; }
}
and
public interface IDocumentView
{
void SetController(IDocumentController controller);
string DisplayName { get; set; }
bool StatusBarVisible { get; set; }
}
Now for my questions. In Seemann's book "Dependency Injection in .NET" he talks about the "Three Calls Pattern" and this is what I have attempted to implement in the above. The code works, the shell view displays and via the MVC pattern my controllers correctly open views etc. However, I am confused as the above definately has the flavour of the "Service Locator Anti-Pattern". In chapter 3 of Seemann's book he states
The COMPOSITION ROOT pattern describes where you should use a DI CONTAINER. However,
it doesn’t state how to use it. The REGISTER RESOLVE RELEASE pattern addresses
this question [...] A DI CONTAINER should be used in three successive
phases called Register, Resolve, and Release.
In its pure form, the REGISTER RESOLVE RELEASE pattern states that you should only
make a single method call in each phase. Krzysztof Kozimic calls this the Three Calls Pattern.
Configuring a DI CONTAINER in a single method call requires more explanation. The
reason that registration of components should happen in a single method call is
because you should regard configuration of a DI CONTAINER as a single, atomic action.
Once configuration is completed, the container should be regarded as read-only.
This sounds like the dredded "Service locator", why is this not deemed service location?
In order to adjust my code to instead use Contstructor Injection, I changed my entry code to
[STAThread]
static void Main()
{
var kernel = new StandardKernel();
kernel.Bind(t => t.FromThisAssembly()
.SelectAllClasses()
.BindAllInterfaces());
FileLogHandler fileLogHandler = new FileLogHandler(Utils.GetLogFilePath());
Log.LogHandler = fileLogHandler;
Log.Trace("Program.Main(): Logging initialized");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(kernel.Get<ApplicationShellView>());
}
using Ninject.Extensions.Conventions, I then changed ApplicationShellController in order to correct my code to inject the IDocumentControllers via ctor injection:
public class ApplicationShellController
{
private IApplicationShellView shellView;
private IEnumerable<IDocumentController> controllers;
public ApplicationShellController(IApplicationShellView shellView, IEnumerable<IDocumentController> controllers)
{
this.shellView = shellView;
this.controllers = controllers;
Log.Trace("ApplicationShellController.Ctor(): Shell initialized successfully");
}
...
}
where
public class SpreadsheetController : IDocumentController
{
private ISpreadsheetView view;
public SpreadsheetController(ISpreadsheetView view)
{
this.view = view;
this.view.SetController(this);
}
...
}
but this leads to a circular dependency, how do I handle this?
Question Summary:
Why is my initial use of Ninject using "Thee Calls Pattern" and CompositionRoot.Resolve<T>() bad or different to the Service Locator Anti-Pattern?
How can I resolve the circular dependency issue above if I want to switch to pure ctor injection?
Thanks very much for your time.
At some point in the process, you have to use service location. However, the difference between DI and SL is that in SL, you are resolving your services at the point they are requested, whereas in DI you resolve them in some kind of factory (such as a controller factory) and then construct your objects and pass the reference in.
You should create some kind of infrastructure that dispatches your commands and uses a factory of some kind to locate the dependencies used by the created objects.
In this way, the rest of your code doesn't have dependency resolution, and you are following a DI pattern except at the construction point.

How to override OnLaunched() from Template10

I am trying to override the OnLaunched() function in a Template 10 Windows Application, but the problem is that it is sealed in Template 10 BootStrapper class (which inherits from the Application class).
Here's my method:
using Windows.UI.Xaml;
...
namespace Sample {
...
sealed partial class App : Template10.Common.BootStrapper {
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
/*************** My stuff *****************
***********************************************/
}
...
}
I am using Template10 Blank app for this app, and the OnLaunched() method in BootStrapper class is this:
namespace Template10.Common
{
public abstract class BootStrapper : Application
{
...
protected sealed override void OnLaunched(LaunchActivatedEventArgs e);
...
}
...
}
I cannot remove the sealed modifier from OnLaunched() in BootStrapper (guess because it is "from metadata").
What's the point of including a sealed method in an abstract class?
Do we get some other method to override, like OnResume(), OnStartAsync(), etc, instead of OnLaunched()?
Update: For reference, here are all the members in BootStrapper:
public abstract class BootStrapper : Application
{
public const string DefaultTileID = "App";
protected BootStrapper();
public static BootStrapper Current { get; }
public TimeSpan CacheMaxDuration { get; set; }
public INavigationService NavigationService { get; }
public StateItems SessionState { get; set; }
public bool ShowShellBackButton { get; set; }
protected Func<SplashScreen, UserControl> SplashFactory { get; set; }
public event EventHandler<WindowCreatedEventArgs> WindowCreated;
public static AdditionalKinds DetermineStartCause(IActivatedEventArgs args);
public NavigationService NavigationServiceFactory(BackButton backButton, ExistingContent existingContent);
[AsyncStateMachine(typeof(<OnInitializeAsync>d__44))]
public virtual Task OnInitializeAsync(IActivatedEventArgs args);
public virtual void OnResuming(object s, object e);
public abstract Task OnStartAsync(StartKind startKind, IActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnSuspendingAsync>d__45))]
public virtual Task OnSuspendingAsync(object s, SuspendingEventArgs e);
public Dictionary<T, Type> PageKeys<T>() where T : struct, IConvertible;
public virtual T Resolve<T>(Type type);
public virtual INavigable ResolveForPage(Type page, NavigationService navigationService);
public void UpdateShellBackButton();
[AsyncStateMachine(typeof(<OnActivated>d__26))]
protected sealed override void OnActivated(IActivatedEventArgs e);
[AsyncStateMachine(typeof(<OnCachedFileUpdaterActivated>d__27))]
protected sealed override void OnCachedFileUpdaterActivated(CachedFileUpdaterActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnFileActivated>d__28))]
protected sealed override void OnFileActivated(FileActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnFileOpenPickerActivated>d__29))]
protected sealed override void OnFileOpenPickerActivated(FileOpenPickerActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnFileSavePickerActivated>d__30))]
protected sealed override void OnFileSavePickerActivated(FileSavePickerActivatedEventArgs args);
protected sealed override void OnLaunched(LaunchActivatedEventArgs e);
[AsyncStateMachine(typeof(<OnSearchActivated>d__31))]
protected sealed override void OnSearchActivated(SearchActivatedEventArgs args);
[AsyncStateMachine(typeof(<OnShareTargetActivated>d__32))]
protected sealed override void OnShareTargetActivated(ShareTargetActivatedEventArgs args);
protected sealed override void OnWindowCreated(WindowCreatedEventArgs args);
public enum AdditionalKinds
{
Primary,
Toast,
SecondaryTile,
Other
}
public enum BackButton
{
Attach,
Ignore
}
public enum ExistingContent
{
Include,
Exclude
}
public enum StartKind
{
Launch,
Activate
}
}
Please help :}
Template 10 does not allow us to override OnLaunched() method. Instead we can override the OnInitializeAsync() and OnStartAsync() methods for this purpose.
The reason is that Template 10 recommends us to use something called the Single Page Model, which is nothing but using a single instance of the Page class to put in the empty Frame provided by the Framework. How is that benefit to us? Well, if we need to put a menu, say a Hamburger menu, in our app, then we need to copy the code for the menu in each and every page we create in our app. This would lead to things like redundancy, inconsistency, WET code, etc. etc.
Therefore, template 10, initially, creates a Page, which they call the Shell, and then contents of each page is loaded into this Shell page, instead of creating new Pages.
We can override these methods in the following way:
sealed partial class App : BootStrapper
{
public App()
{
this.InitializeComponent();
}
public override Task OnInitializeAsync(IActivatedEventArgs args)
{
var nav = NavigationServiceFactory(BackButton.Attach, ExistingContent.Include);
Window.Current.Content = new Views.Shell(nav);
return Task.FromResult<object>(null);
}
public override Task OnStartAsync(BootStrapper.StartKind startKind, IActivatedEventArgs args)
{
NavigationService.Navigate(typeof(Views.MainPage));
return Task.FromResult<object>(null);
}
}
Here's where I figured the answer:
https://github.com/Windows-XAML/Template10/wiki/Docs-%7C-HamburgerMenu
So, long story short, override OnInitializeAsync() or OnStartAsync(), instead of OnLaunched().
You're trying to override OnLaunched in MyPage.xaml.cs and I'm pretty safe to assume that your MyPage class does not inherit from Application. So it does not have OnLaunched() method (at least not with that signature). What you need to do is override it in App.xaml.cs, as it's Application.OnLaunched(). App class, which is in App.xaml.cs, inherits from Application.
By the way, this is the example from the blank app template, which you've mentioned:

Categories

Resources