我正试图在UWP上捕捉TabbedPage
的重拍事件。
从this page,我可以看到你需要创建一个自定义渲染器。当我尝试使用Xamarin.Forms.Platform.UWP.TabbedPageRenderer
时,我找不到任何适当的事件来订阅。
我已经尝试了Tapped
和Focused
事件,但它们似乎没有像我期望的那样工作。
如何检测UWP上是否重新点击了标签?
这是我到目前为止所尝试的:
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();
}
}
}
简单的回答是,据我所知,你不能轻易地检测UWP上的标签重新选择/重选,至少没有深入研究Xamarin.Forms源代码,看看他们是如何实现uWP TabbedPageRenderer的。
以下是我实现它的方法:
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;
}
}
}
TabbedPageHeaderTextBlock是UWP渲染器内部的一部分。鉴于它没有记录,这并不理想,因为它理论上可以改变未来版本的Xamarin.Forms,但它已经稳定了一段时间。
这应该足以为你解决,但更多细节在这里:https://criticalhittech.com/2017/09/25/tab-reselection-in-xamarin-forms-part-2/。
基于DavidS的答案,这里是我使用的代码,它也处理UWP选项卡中的图标:
// 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;
}
}
}
根据您的解释,我已更新您的代码,希望这将有所帮助:
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;
}
}