全局路由目前不能是堆栈中的唯一页面
Global routes currently cannot be the only page on the stack
让弹出菜单按照我希望的方式在 Xamarin Forms 中工作一直是一个很大的痛苦。如果用户已登录,我试图让某个菜单项(我的统计信息)转到某个页面,如果用户未登录,则转到另一个页面(登录页面)。我尝试了两种不同的方法但没有成功。
方法一
首先,我尝试在 XAML 中使用指定路线在 Shell 内容中设置弹出项目,如下所示:
<FlyoutItem Title="My Stats" Icon="icon_feed.png">
<ShellContent x:Name="shellContent_myStats" Route="MyStatsPage" ContentTemplate="{DataTemplate local:MyStatsPage}" />
</FlyoutItem>
然后我会在用户登录时以编程方式修改路由 in/out:
//Logging Out
shellContent_myStats.ContentTemplate = new DataTemplate(typeof(LoginPage));
Routing.SetRoute(shellContent_myStats, "LoginPage");
...
//Logging In
shellContent_myStats.ContentTemplate = new DataTemplate(typeof(MyStatsPage));
Routing.SetRoute(shellContent_myStats, "MyStatsPage");
我无法让它工作。无论出于何种原因,只有第一个执行的部分才会生效。例如,如果我在注销时启动应用程序,它会按预期定向到登录页面,但在我注销后不会切换。反之亦然,如果我在登录时启动应用程序,它会按预期导航到“我的统计信息”页面,但即使在我注销后也会继续这样做。
我尝试了上述代码的几种不同变体,但均无济于事。
方法二
我尝试的第二种方法是在 XAML 中使用 OnClick 事件处理程序指定菜单项,如下所示:
<MenuItem Text="My Journey" StyleClass="MenuItemLayoutStyle" Clicked="OnMyStatsClicked"/>
后面的代码:
public AppShell()
{
//Route now needs to be registered in page constructor
Routing.RegisterRoute(nameof(MyStatsPage), typeof(MyStatsPage));
...
public async void OnMyStatsClicked(object sender, EventArgs e)
{
Shell.Current.FlyoutIsPresented = false;
if (LoggedIn)
{
// Prefixing with `//` switches to a different navigation stack instead of pushing to the active one
await Shell.Current.GoToAsync($"//{nameof(MyStatsPage)}");
}
else
{
await Shell.Current.GoToAsync($"//{nameof(LoginPage)}");
}
}
...
现在,当我 select 使用此设置(登录时)的菜单项时,它会抛出以下错误:
System.Exception: 'Global routes currently cannot be the only page on the stack, so absolute routing to global routes is not supported. For now, just navigate to: MyStatsPage'
如果我按照删除路线中的两个斜线 ("//") 给出的建议进行操作,则导航可以正常工作,但是左上角的弹出菜单不可用,取而代之的是后退按钮。这是不需要的,我希望菜单仍然可用。为什么我不能在后面的代码中定义的路由上使用绝对路由..?
对于所提到的两种方法中的任何一种,我都非常感谢您提出任何建议,以使其正常工作。几天来一直在尝试做一些看似如此简单的事情。谢谢
您可以使用 属性 FlyoutItemIsVisible
设置技巧,ShellContent
(因此相关页面)将在 Shell 层次结构中注册,但不会'它在弹出窗口中不可见,而且它只会在需要时加载,因为我们使用的是 ContentTemplate
.
假设您只使用没有底部标签的弹出窗口:
AppShell.xaml
<Shell Shell.TabBarIsVisible="False"
...
<FlyoutItem>
<ShellContent ContentTemplate="{DataTemplate local:MainPage}"/>
<ShellContent Route="AnotherPage"
FlyoutItemIsVisible="False"
ContentTemplate="{DataTemplate local:AnotherPage}"/>
<ShellContent Route="LoginPage"
FlyoutItemIsVisible="False"
ContentTemplate="{DataTemplate local:LoginPage}"/>
</FlyoutItem>
<MenuItem Text="My Stats Page"
Clicked="MenuItem_Clicked"/>
AppShell.xaml.cs
async void MenuItem_Clicked(object sender, System.EventArgs e)
{
if (LoggedIn)
await Shell.Current.GoToAsync($"//{nameof(AnotherPage)}");
else
await Shell.Current.GoToAsync($"//{nameof(LoginPage)}");
}
备注
如果您同时使用底部选项卡,或者作为另一种方法,我建议将不相关的页面隐藏到当前日志状态(例如:如果用户已登录,则隐藏 LoginPage)。
让弹出菜单按照我希望的方式在 Xamarin Forms 中工作一直是一个很大的痛苦。如果用户已登录,我试图让某个菜单项(我的统计信息)转到某个页面,如果用户未登录,则转到另一个页面(登录页面)。我尝试了两种不同的方法但没有成功。
方法一
首先,我尝试在 XAML 中使用指定路线在 Shell 内容中设置弹出项目,如下所示:
<FlyoutItem Title="My Stats" Icon="icon_feed.png">
<ShellContent x:Name="shellContent_myStats" Route="MyStatsPage" ContentTemplate="{DataTemplate local:MyStatsPage}" />
</FlyoutItem>
然后我会在用户登录时以编程方式修改路由 in/out:
//Logging Out
shellContent_myStats.ContentTemplate = new DataTemplate(typeof(LoginPage));
Routing.SetRoute(shellContent_myStats, "LoginPage");
...
//Logging In
shellContent_myStats.ContentTemplate = new DataTemplate(typeof(MyStatsPage));
Routing.SetRoute(shellContent_myStats, "MyStatsPage");
我无法让它工作。无论出于何种原因,只有第一个执行的部分才会生效。例如,如果我在注销时启动应用程序,它会按预期定向到登录页面,但在我注销后不会切换。反之亦然,如果我在登录时启动应用程序,它会按预期导航到“我的统计信息”页面,但即使在我注销后也会继续这样做。
我尝试了上述代码的几种不同变体,但均无济于事。
方法二
我尝试的第二种方法是在 XAML 中使用 OnClick 事件处理程序指定菜单项,如下所示:
<MenuItem Text="My Journey" StyleClass="MenuItemLayoutStyle" Clicked="OnMyStatsClicked"/>
后面的代码:
public AppShell()
{
//Route now needs to be registered in page constructor
Routing.RegisterRoute(nameof(MyStatsPage), typeof(MyStatsPage));
...
public async void OnMyStatsClicked(object sender, EventArgs e)
{
Shell.Current.FlyoutIsPresented = false;
if (LoggedIn)
{
// Prefixing with `//` switches to a different navigation stack instead of pushing to the active one
await Shell.Current.GoToAsync($"//{nameof(MyStatsPage)}");
}
else
{
await Shell.Current.GoToAsync($"//{nameof(LoginPage)}");
}
}
...
现在,当我 select 使用此设置(登录时)的菜单项时,它会抛出以下错误:
System.Exception: 'Global routes currently cannot be the only page on the stack, so absolute routing to global routes is not supported. For now, just navigate to: MyStatsPage'
如果我按照删除路线中的两个斜线 ("//") 给出的建议进行操作,则导航可以正常工作,但是左上角的弹出菜单不可用,取而代之的是后退按钮。这是不需要的,我希望菜单仍然可用。为什么我不能在后面的代码中定义的路由上使用绝对路由..?
对于所提到的两种方法中的任何一种,我都非常感谢您提出任何建议,以使其正常工作。几天来一直在尝试做一些看似如此简单的事情。谢谢
您可以使用 属性 FlyoutItemIsVisible
设置技巧,ShellContent
(因此相关页面)将在 Shell 层次结构中注册,但不会'它在弹出窗口中不可见,而且它只会在需要时加载,因为我们使用的是 ContentTemplate
.
假设您只使用没有底部标签的弹出窗口:
AppShell.xaml
<Shell Shell.TabBarIsVisible="False"
...
<FlyoutItem>
<ShellContent ContentTemplate="{DataTemplate local:MainPage}"/>
<ShellContent Route="AnotherPage"
FlyoutItemIsVisible="False"
ContentTemplate="{DataTemplate local:AnotherPage}"/>
<ShellContent Route="LoginPage"
FlyoutItemIsVisible="False"
ContentTemplate="{DataTemplate local:LoginPage}"/>
</FlyoutItem>
<MenuItem Text="My Stats Page"
Clicked="MenuItem_Clicked"/>
AppShell.xaml.cs
async void MenuItem_Clicked(object sender, System.EventArgs e)
{
if (LoggedIn)
await Shell.Current.GoToAsync($"//{nameof(AnotherPage)}");
else
await Shell.Current.GoToAsync($"//{nameof(LoginPage)}");
}
备注
如果您同时使用底部选项卡,或者作为另一种方法,我建议将不相关的页面隐藏到当前日志状态(例如:如果用户已登录,则隐藏 LoginPage)。