Reputation: 9583
I am trying to capture a retap event for a TabbedPage
on UWP.
From this page, I can see that you need to create a custom renderer. When I try to use Xamarin.Forms.Platform.UWP.TabbedPageRenderer
, I can't find any appropriate event to subscribe to.
I have tried the Tapped
and Focused
events, but they do not seem to work as I expect.
How do you detect if a tab is re-tapped on UWP?
Here is what I have tried so far:
public class TabbedPageCustomRenderer : TabbedPageRenderer
{
private TabbedHomePage _page;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_page = (TabbedHomePage)e.NewElement;
}
else
{
_page = (TabbedHomePage)e.OldElement;
}
//_page.Focused += _page_Focused;
//this.Control.Tapped += Control_Tapped;
// what should I subscribe to?
}
private async void _page_Focused(object sender, Xamarin.Forms.FocusEventArgs e)
{
if (_page?.CurrentPage?.Navigation != null && _page.CurrentPage.Navigation.NavigationStack.Count > 0)
{
await _page.CurrentPage.Navigation.PopToRootAsync();
}
}
private async void Control_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
if (_page?.CurrentPage?.Navigation != null && _page.CurrentPage.Navigation.NavigationStack.Count > 0)
{
await _page.CurrentPage.Navigation.PopToRootAsync();
}
}
}
Upvotes: 0
Views: 283
Reputation: 9583
Based on the answer from DavidS, here is the code I used, which also handles icons in the UWP tab:
// this is C# 7, so will only work with a recent c# compiler
public class TabbedPageCustomRenderer : TabbedPageRenderer
{
private Xamarin.Forms.Page _prevPage;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
Control.Tapped += Control_Tapped;
_prevPage = Control.SelectedItem as Xamarin.Forms.Page;
}
private async void Control_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
// replace 'TabbedHomePage' with whatever your page type is with the tabs
if (!(this.Element is TabbedHomePage))
return;
switch (e.OriginalSource)
{
case Image image when image.Parent is StackPanel:
{
var sp = (StackPanel)image.Parent;
var tb = sp.Children.Where(c => c is TextBlock).FirstOrDefault() as TextBlock;
await HandleRetab(tb);
break;
}
case TextBlock tb:
{
await HandleRetab(tb);
break;
}
default:
break;
}
async Task HandleRetab(TextBlock tb)
{
if (tb == null)
return;
var newPage = tb.DataContext as Xamarin.Forms.Page;
if (newPage == _prevPage &&
tb.Name == "TabbedPageHeaderTextBlock")
{
// do your thing here, a tab retap happened, like:
await newPage.Navigation.PopToRootAsync();
}
_prevPage = newPage;
}
}
}
Upvotes: 1
Reputation: 2934
The short answer is that no, as far as I can tell, you can't easily detect tab retap/reselect on UWP, at least without digging into the Xamarin.Forms source code a bit to see how they implemented the uWP TabbedPageRenderer.
Here is how I implemented it:
public class MainTabPageRenderer : TabbedPageRenderer
{
private Xamarin.Forms.Page _prevPage;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
Control.Tapped += Control_Tapped;
_prevPage = Control.SelectedItem as Xamarin.Forms.Page;
}
private async void Control_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
var src = e.OriginalSource as TextBlock;
if (src != null
&& src.Name == "TabbedPageHeaderTextBlock"
&& Element is TabReselectDemo.MainPage)
{
var newPage = src.DataContext as Xamarin.Forms.Page;
if (newPage == _prevPage)
{
// do your thing here, a tab retap happened, like:
await newPage.Navigation.PopToRootAsync();
}
_prevPage = newPage;
}
}
}
The TabbedPageHeaderTextBlock is part of the internals of the UWP renderer. Given that it's not documented, this isn't ideal as it could theoretically change on a future version of Xamarin.Forms, but it has been stable for a while.
That should be enough to solve it for you, but more details here: https://criticalhittech.com/2017/09/25/tab-reselection-in-xamarin-forms-part-2/.
Upvotes: 1
Reputation: 1595
Based on your explanation I have update your code, hope this will help:
public class TabbedPageCustomRenderer : TabbedPageRenderer
{
private TabbedHomePage _page;
bool isRetap = false;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_page = (TabbedHomePage)e.NewElement;
}
else
{
_page = (TabbedHomePage)e.OldElement;
}
//_page.Focused += _page_Focused;
this.Control.Tapped += Control_Tapped;
// what should I subscribe to?
}
private async void _page_Focused(object sender, Xamarin.Forms.FocusEventArgs e)
{
if (_page?.CurrentPage?.Navigation != null && _page.CurrentPage.Navigation.NavigationStack.Count > 0)
{
await _page.CurrentPage.Navigation.PopToRootAsync();
}
}
private async void Control_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
if (isRetap && _page?.CurrentPage?.Navigation != null && _page.CurrentPage.Navigation.NavigationStack.Count > 0)
{
await _page.CurrentPage.Navigation.PopToRootAsync();
}
isRetap = true;
}
}
Upvotes: 0