OnBackPressed Xamarin PCL where do i override the method - c#

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.

Related

Custom Picker Renderer bug - Picker displays twice upon calling Picker.Focus()

I am trying to employ a custom renderer for my Picker controls. I also need my Picker to fire up when I open a tab. I do this by calling the picker's Focus() method on tab SelectionChanged.
if (e.NewPosition == 1)
{
myPicker.Focus();
}
This, however, fires up two instances of the picker alert at the same time; one is the default renderer, the second one is my custom renderer. They are one atop the other, such that when I close the one with my custom renderer, the one with default renderer is visible.
Simply tapping the Picker will display only one instance, with the custom renderer (this works as intended).
I wrote my custom renderer following this post's answer.
I tried the answer described here, but the problem is that this skips over the second instance of the picker, which is not what I need. I need to keep the instance that has my custom renderer, not the one with the default renderer.
I also tried to make sure that I am running on the right thread, implementing code described in this question's answers.
Moreover, I tried to somehow remove events from the CustomRenderer and add them again, like this:
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Picker> e)
{
base.OnElementChanged(e);
Control.Click += null; // hoping this would override all existing events
Control.Click += Control_Click;
}
Finally, this question came closest to my situation and I tried following the solutions described in the answers.
None of these worked. I believe that when Focus() is called, somehow the default renderer shows up first due to my custom renderer inheriting the default PickerRenderer.
How do I enforce the custom renderer?
Or is there a different way for me to fire up my picker upon changing tabs, instead of calling Focus()?
My project runs on Xamarin.Forms 5.0.0.2545 (latest version as of when I'm writing this question).
EDIT
I observed the following behaviour: Control.Click event is fired AFTER the default renderer is displayed. By debugging the app and placing a break point inside my Control.Click handler function, I can see that the app first opens the default picker, and then it halts in said breakpoint.
SOLVED
By studying the PickerRenderer.cs class, I realised that there were more functions that had to be overwritten.
To begin with, I made my custom renderer class implement the IPickerRenderer interface and added the following function:
void IPickerRenderer.OnClick()
{
Control_Click(this, null); // this function handles the Control.Click event
}
Moreover, I overwrite the CallOnClick() function:
public override bool CallOnClick()
{
Control_Click(this, null); // same function, that handles the Control.Click event
return true;
}
Finally, I added this bit of code (thanks to this answer) that ensures the Picker shows up only once. Thus, my OnElementChanged function looks like this:
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Focusable = false;
}
Control.Click += Control_Click; // this is where I link the handler to the event
}
The conclusion is that the described behaviour either
wasn't a bug, which means I just hadn't implemented it correctly
was a bug, and I managed to find a good workaround
Either way, I managed to solve my problem.
If anyone else stumbles upon this, I hope my work helps.

Xamarin.Forms physical key press event handling

I'm developing Xamarin Forms app and I need to handle an event when physical button is pressed (on Android). What I've found out is that I can use DispatchKeyEvent inside an activity in Xamarin.Android project. However I don't know specifically how to do it.
In the shared code I have defined a ContentPage and I'm trying to override the DispatchKeyEvent inside a custom page renderer in Xamarin.Android. However, I get an error about missing constructor (I suppose it is related to layout, which is defined in the shared code, but I don't know why Xamarin.Android renderer doesn't use it).
How to solve this problem? Maybe there is some easier way to get info about key being pressed?
In the code behind for your page, you can override OnBackButtonPressed.
protected override bool OnBackButtonPressed()
{
return base.OnBackButtonPressed();
}

Custom handling of OnBackPressed MvvmCross - don't close app

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).

How to intercept Navigation Bar Back Button Clicked Prism Xamarin Forms?

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

Caliburn.Micro and app resume

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).

Categories