0

I have two navigation pages, one root page, and a second page that can be accessed from the first. I have no desire to prescribe a separate button for this when there is an arrow at the top. Is it possible to somehow register a Clicked event handler for it yourself?

  • I have no idea what you're trying to do. What do you want to do with the back arrow that is different from the standard back navigation? – Jason Jun 04 '22 at 19:59
  • I believe you want to subscribe to your page's navigation events, and then from there you can handle what happens when users click the back button or the arrow on the screen. You could subscribe to `Shell.Current.Navigating` in your `OnAppearing` method in your page to intercept any navigation. This will also capture if the user presses the native back button on the device. Perhaps this will help: https://stackoverflow.com/a/68795321/3579174 – Ibrennan208 Jun 04 '22 at 21:47
  • @Jason , I have a device that works in four modes, when I disconnect from its IP, I must also disconnect the device itself. That's why I need to register it in the handler of this arrow. And I can't do that. – YaKotikTvoy Jun 05 '22 at 10:13

2 Answers2

0

From what you are asking, I believe you are trying to have an event handler that can intercept navigation events.

Xamarin.Forms Shell has a Navigating event you can subscribe to that allows you to see the current navigation, where it intends to navigate to, and allows you to cancel navigation or redirect. This captures all navigation, so it isn't just the back button, but will also capture moving forward as well.

Here is an example of navigation being intercepted in a ContentPage:

 public class ExampleContentPage : ContentPage
    {
        public ExampleContentPage()
        {
            Content = new StackLayout
            {
                Children = {
                    new Label { Text = "Welcome to Xamarin.Forms!" }
                }
            };
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            // subscribe to event listener on appearing
            Shell.Current.Navigating += Current_Navigating;
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();

            // remove event listener on disappearing
            Shell.Current.Navigating -= Current_Navigating;
        }

        private async void Current_Navigating(object sender, ShellNavigatingEventArgs e)
        {
            if (sender is Shell shell)
            {

                // cancels navigation so we can do what we need
                if (e.CanCancel)
                {
                    e.Cancel();
                }



                // continue navigation to it's original target if we so choose
                Shell.Current.Navigating -= Current_Navigating;
                await Shell.Current.GoToAsync(e.Target, true);
            }
        }
    }

However; if you're looking to override the functionality of the arrow button, I think you need to define the Shell's BackButtonBehavior.

This can be done either through XAML or C#. I've attached Microsoft's examples here:

<ContentPage ...>    
    <Shell.BackButtonBehavior>
        <BackButtonBehavior Command="{Binding BackCommand}"
                            IconOverride="back.png" />   
    </Shell.BackButtonBehavior>
    ...
</ContentPage>
Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
    Command = new Command(() =>
    {
        ...
    }),
    IconOverride = "back.png"
});

And here is the documentation for overriding the back button behavior: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation#back-button-behavior

Ibrennan208
  • 1,345
  • 3
  • 14
  • 31
0

To handle the backbutton event on android, you can override the OnOptionsItemSelected and OnBackPressed method in mainactivity, like:

public override void OnBackPressed()
        {
            // this is not necessary, but in Android user 
            // has both Nav bar back button and
            // physical back button its safe 
            // to cover the both events

            // retrieve the current xamarin forms page instance
            var currentpage = (BackArrowTest)
            Xamarin.Forms.Application.
            Current.MainPage.Navigation.
            NavigationStack.LastOrDefault();

            // check if the page has subscribed to 
            // the custom back button event
            if (currentpage?.CustomBackButtonAction != null)
            {
                currentpage?.CustomBackButtonAction.Invoke();
            }
            else
            {
                base.OnBackPressed();
            }
        }
        public override bool OnOptionsItemSelected(IMenuItem item)
        {
            // check if the current item id 
            // is equals to the back button id
            if (item.ItemId == 16908332)
            {
                // retrieve the current xamarin forms page instance
                var currentpage = (BackArrowTest)
                Xamarin.Forms.Application.
                Current.MainPage.Navigation.
                NavigationStack.LastOrDefault();

                // check if the page has subscribed to 
                // the custom back button event
                if (currentpage?.CustomBackButtonAction != null)
                {
                    // invoke the Custom back button action
                    currentpage?.CustomBackButtonAction.Invoke();
                    // and disable the default back button action
                    return false;
                }

                // if its not subscribed then go ahead 
                // with the default back button action
                return base.OnOptionsItemSelected(item);
            }
            else
            {
                // since its not the back button 
                //click, pass the event to the base
                return base.OnOptionsItemSelected(item);
            }
        }

Then you can create a page which has EnableBackButtonOverrideProperty and your custom event like:

public class BackArrowTest : ContentPage
    {
        public Action CustomBackButtonAction { get; set; }
        public static readonly BindableProperty EnableBackButtonOverrideProperty =
               BindableProperty.Create(
               nameof(EnableBackButtonOverride),
               typeof(bool),
               typeof(BackArrowTest),
               false);
        public bool EnableBackButtonOverride
        {
            get
            {
                return (bool)GetValue(EnableBackButtonOverrideProperty);
            }
            set
            {
                SetValue(EnableBackButtonOverrideProperty, value);
            }
        }}

At last you can set the event:

<bk:BackArrowTest  xmlns:bk="clr-namespace:MyForms2"
                   xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
EnableBackButtonOverride="True"
 x:Class="MyForms2.MyPage1"
  >
    
        <StackLayout>
            <Label Text="Welcome to Xamarin.Forms!"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
   
</bk:BackArrowTest>

codebehind:

public partial class MyPage1 : BackArrowTest
    {
        public MyPage1()
        {
         
            InitializeComponent();
            this.EnableBackButtonOverride = true;
            this.CustomBackButtonAction = () => { Console.WriteLine("Do something"); };
        }
    }

FYI:don't forget to set the Actionbarsupport in mainactivity like:

  AndroidX.AppCompat.Widget.Toolbar toolbar = this.FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);
Adrain
  • 1,946
  • 1
  • 3
  • 7