[英]How to differentiate StartUp screens in Xamarin Forms Shell
我有注册/登录部分以及主要内容。
主要内容有标签栏部分(向下标签),但我只想在主要部分显示这些标签。 注册/登录部分没有。 首先,在我的 App.cs 中,我需要检查用户是否存在(来自安全商店的凭据),并根据我的 api 作为答案返回的内容,我需要向用户显示正确的页面(注册时他上次停止的某个步骤,或者如果凭据正常,将即时消息重定向到带有向下选项卡的主扇区)
我按如下方式设置我的 AppShell:
<ShellItem Route="login">
<ShellContent ContentTemplate="{DataTemplate login:Page1}" />
<ShellContent ContentTemplate="{DataTemplate login:Page2}" />
</ShellItem>
<ShellItem Route="register">
<ShellContent ContentTemplate="{DataTemplate register:RegisterPage1}" />
<ShellContent ContentTemplate="{DataTemplate register:RegisterPage2}" />
<ShellContent ContentTemplate="{DataTemplate register:RegisterPage3}" />
</ShellItem>
<TabBar Route="main">
<Tab Title="Activity" Icon="tab_feed.png">
<ShellContent ContentTemplate="{DataTemplate postlogin:ActivityPage}" />
</Tab>
<Tab Title="Invest" Icon="tab_about.png">
<ShellContent ContentTemplate="{DataTemplate postlogin:InvestPage}" />
</Tab>
</TabBar>
知道我想以某种方式告诉 AppShell 的代码隐藏,根据我的 api 响应转到特定的路由页面。 我试过类似的东西:
public AppShell()
{
MainThread.BeginInvokeOnMainThread(async () =>
{
await Shell.Current.GoToAsync("//register");
});
InitializeComponent();
}
但我有空引用异常。 你有更好的架构解决方案吗?
我认为您应该将登录和注册页面与外壳分开处理。 换句话说,当应用程序启动时,检查用户是否需要登录/注册。 如果是这样,将登录和/或注册页面作为模态页面推送,覆盖 Shell 界面。 完成登录/注册后,弹出模态页面,您将进入带有选项卡的 Shell。
或者,您可以在应用启动时将Application.MainPage
分配给您的登录或注册页面,然后在完成后将Application.MainPage
重新分配给AppShell
,例如:
MainPage = new LoginPage();
// Authenticated!! - now open the shell
MainPage = new AppShell();
更新:虽然我没有理由确保登录/注册页面“在外壳中”,特别是因为有人说他们在显示注册/登录页面时不想要标签,但问题是开头问题中的代码是他们在 AppShell 构造函数期间调用 Shell.Current。 您可以通过添加await Task.Delay(500)
来避免该错误,让 AppShell 完成构造(您可能应该先调用InitializeComponent
),例如:
public AppShell()
{
InitializeComponent();
MainThread.BeginInvokeOnMainThread(async () =>
{
await Task.Delay(500);
await Shell.Current.GoToAsync("//register");
});
}
然而,这确实违背了建议不要从构造函数启动异步方法的最佳实践。 这是关于替代方案的博客文章: https : //blog.stephencleary.com/2013/01/async-oop-2-constructors.html
例如做这样的事情:
public sealed class MyClass
{
private MyData asyncData;
private MyClass() { ... }
private async Task<MyClass> InitializeAsync()
{
asyncData = await GetDataAsync();
return this;
}
public static Task<MyClass> CreateAsync()
{
var ret = new MyClass();
return ret.InitializeAsync();
}
}
public static async Task UseMyClassAsync()
{
MyClass instance = await MyClass.CreateAsync();
...
}
用以下代码替换您的代码并享受:)
InitializeComponent();
MainThread.BeginInvokeOnMainThread(async () =>
{
await GoToAsync("//register");
});
你可以试试这个,你不需要从Shell
单独login/registration
。 它将根据它在AppShell
放置方式简单地加载。 然后通过首选项,您可以说要从头开始导航的位置。
我在我的一个项目中进行了这项工作。
AppShell.cs:
public AppShell()
{
InitializeComponent();
RegisterRoutes();
bool mainLogin = Preferences.ContainsKey(Settings.RememberLogin);
if (mainLogin)
{
_ = GoToAsync("//Main");
}
}
private void RegisterRoutes()
{
Routing.RegisterRoute("Register", typeof(RegisterPage));
Routing.RegisterRoute("Login", typeof(LoginPage));
}
AppShell.xaml:
<ShellItem Route="MainPage" Shell.FlyoutBehavior="Disabled"
FlyoutItemIsVisible="False" Shell.ForegroundColor="White" Shell.TitleColor="White"
Shell.BackgroundColor="{StaticResource Primary}">
<ShellContent ContentTemplate="{DataTemplate local:MainPage}" />
</ShellItem>
<TabBar Route="Main">
<Tab Title="Activity" Icon="tab_feed.png">
<ShellContent ContentTemplate="{DataTemplate postlogin:ActivityPage}" />
</Tab>
<Tab Title="Invest" Icon="tab_about.png">
<ShellContent ContentTemplate="{DataTemplate postlogin:InvestPage}" />
</Tab>
</TabBar>
主页.xaml:
<Button Command="{Binding GoToLoginPageCommand}" />
<Button Command="{Binding GoToRegisterPageCommand}" />
当登录正确时:
Preferences.Set(Settings.RememberLogin, true);
await Shell.Current.GoToAsync("//Main");
您将不得不使其适应您的项目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.