TabbedPage 上的 Retap 事件
Retap event on TabbedPage
我正在尝试在 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();
}
}
}
根据您的解释,我更新了您的代码,希望对您有所帮助:
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;
}
}
简短的回答是,不,据我所知,您无法在 UWP 上轻松检测到选项卡 retap/reselect,至少在不深入研究 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;
}
}
}
我正在尝试在 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();
}
}
}
根据您的解释,我更新了您的代码,希望对您有所帮助:
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;
}
}
简短的回答是,不,据我所知,您无法在 UWP 上轻松检测到选项卡 retap/reselect,至少在不深入研究 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;
}
}
}