I'd like to add custom handling of method OnBackPressed in Xamarin Android with MvvmCross framework. I've tried something like this:
[Activity(Label = "Table", NoHistory = true)]
public class Table: MvxActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.View_Table);
}
public override void OnBackPressed()
{
//base.OnBackPressed();
SetContentView(Resource.Layout.View_MainMenu);
}
}
and the app went to MainMenuView but one single button (which directs to TableView) inside this view was disabled.
I've been trying with something like:
protected override void OnResume()
{
SetContentView(Resource.Layout.View_MainMenu);
}
in MainMenuView but it doesn't work. Should I add some piece of code into ViewModels instead of in Views? Or bind somehow events in a layout? If it is possible to handle that kind of behavior, how to achieve that?
You are not using MvvmCross features if you write your code like this.
Just remove "History = true", remove your OnBackPressed() and OnResume() handlers and MvvmCross will handle your back to MainMenu as expected.
When using MvvmCross, you need to use your ViewModels and not your Views to navigate (at least, in a classic scenario).
Related
I am trying to override the OnBackPressed() method in a pcl project. I do not know where i must ovveride it. In the portable project or in the android? I want to navigate to another page when i click the back button. Any suggestions?
You need to override OnBackButtonPressed in your PCL project on your custom Page classes.
protected override bool OnBackButtonPressed()
{
// call your custom navigation code here
// returning true because you are handling the navigation
return true;
}
Note that this event is raised when the hardware back button is pressed but will not be raised on iOS.
Basically Its the same question from Here but the solution dosen't work for Prism MVVM because the OnOptionsItemSelected(IMenuItem item) in the MainActivity never get raised.
For the hardware button I'm using on that page:
protected override bool OnBackButtonPressed()
{
return !PageUtilities.CanNavigate(this, null);
}
Found the answer here https://xamarindevelopervietnam.wordpress.com/2016/11/19/how-to-handle-hardwaresoftware-back-button-from-viewmodel-in-xamarin-forms/
works well
you can do like this
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
e.Cancel = !PageUtilities.CanNavigate(this, null);
base.OnBackKeyPress(e);
}
Cancel the event when navigation neeeds to be stopped
I guess there is no straight or single answer to this.
Based on your requirement you must need to provide MVVM implementation.
Latest Prism Library update has the OnNavigatedFrom method (you'll require to override by implementing INavigationAware interface)
public virtual void OnNavigatedFrom(NavigationParameters parameters)
{
// here is the place you would require to handle the Back button event,
// this is fired every-time, user tries to leave the view.
}
public virtual void OnNavigatedTo(NavigationParameters parameters)
{
// fired upon view load
}
You may require a static (boolean or something) variable to keep a check if the user is leaving the view and optionally display a message or invalidate the action.
Hope this helps.
Regards,
N Baua
I am using IRegionManager to load and navigate to views, I have no problem loading content to my main region in my main view which is loaded with my bootstrapper class but I cant load content to regions inside my loaded views, the region manager does not seem to be registering these regions.
my bootstrapper class:
protected override DependencyObject CreateShell()
{
return this.Container.Resolve<MainWindowView>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow.Show();
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
this.Container.RegisterTypeForNavigation<DocumentView>();
this.Container.RegisterTypeForNavigation<EmailView>();
this.Container.RegisterTypeForNavigation<WorkTypeSelectionView>();
}
the DocumentView is user control with another region the method that runs when the command is triggered is this:
private void ViewEmailAction()
{
NavigationParameters parameters;
parameters = new NavigationParameters();
parameters.Add(nameof(this.CurrentEmail), this.CurrentEmail);
this.regionManager.Regions[this.EmailRegion].RequestNavigate(nameof(EmailView), parameters);
}
This throws and exception with the message "The region manager does not contain the EmailRegion region."
Thanks in advance!
There are two different things going on here:
UserControls:
This should work with not issues whatsoever. Chances are that you are trying to navigate to a region that is defined in a View that hasn't been loaded yet. Make sure you are navigating to a region after it has been loaded. Navigating inside of ViewModel constructors is one of the biggest sources of this problem. If you want to post your sample to GitHub, I can take a look.
ControlTemplates:
This is a known issue in Prism. Here is your fix:
http://southworks.com/blog/2011/11/10/regions-inside-datatemplates-in-prism-v4-using-a-region-behavior/
In my Windows Phone Silverlight 8.1 app I enabled the app resume (ActivationPolicy="Resume")
When the user re-open the app (using the main tile), the OnDeactivate method of the ViewModel is called after the OnActivation method.
Is it correct?
How can I handle the app resume with Caliburn.Micro?
Here is the code of the ViewModel:
public class Page2ViewModel: Screen
{
protected override void OnActivate()
{
base.OnActivate();
}
protected override void OnDeactivate(bool close)
{
base.OnDeactivate(close);
}
}
This does not seem right. OnDeactivate is called when navigating away from a View. In your ViewModel there is no way to directly differentiate if it was activated from normal navigation or because of resuming.
Take a look at your Bootstrapper, you can override OnActivate and OnLaunch methods there that correspond to Application_Launching and Application_Activated. OnActivate is the one you want.
The problem was in the AppBootstrapper.
To handle the app fast resume, the Navigated and Navigating events must be subscribed in the CreatePhoneApplicationFrame frame.
In this repository the fix (see commit list for the history).
First of all this is my first contact with Caliburn.Micro, C# and WPF. I have gone through the Calibur.Micro tutorial and stopped in the moment of "All about actions" and First View subsection. Author wrote the solution for Silverlight application as follow:
public class MefBootstrapper : BootstrapperBase
{
//same as before
protected override void OnStartup(object sender, StartupEventArgs e)
{
Application.RootVisual = new ShellView();
}
//same as before
}
So this is solution how to say bootstrapper which view use as base to show. About WPF I get only enigmatic information:
In this scenario, we simply override OnStartup, instantiate the view
ourselves and set it as the RootVisual (or call Show in the case of
WPF).
So the Silverlight example is very clear for me, we just manually instantiate the proper View to property Application.RootVisual. But is for me totally unclear what is the Show method, which member it is. How to call it.
Thanks for help!
Caliburn.Micro provides a BootstrapperBase class from which you can inherit your own bootstrapper class. It has a virtual method OnStartup which you can override to do the initialization of your shellview. It also provides a utility method DisplayRootViewFor which can be used for displaying the related view for a specified viewmodel type.
So a simple implementation would look like this,
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<TShellViewModel>();
}
where TShellViewModel is the type of your Shell ViewModel. Framework will resolve the view using convention and does the necessary groundwork to display the same. This link will provide a broader picture for a MEF based IOC supported bootstrapper implementation for WPF.