我有一个由几种页面类型组成的Xamarin应用程序。我正在使用棱镜。
我希望应用的导航目标是主页内应用中的嵌套视图,而不是主页本身,以便将MainPage
用作始终存在的外部框架,并且嵌套页面托管应用的导航服务。
通过这种方式,我可以始终存在一些控件(即后退/前进/主页)。 如何将NavigationService
的"MainPage
"配置为实际MainPage
中的嵌套页面?
我是XF的新手,以前没有使用过NavigationPage
,但它在这里有什么用吗?
你没有。Prism的导航服务将不支持您尝试执行的操作,因为INavigationService
是基于Page
的。 听起来你的方法非常不正统。 为什么不直接使用NavigationPage
并在自定义渲染器中或作为工具栏项提供选项?
Prism的INavigationService
不是为了做你想做的事情而设计的。 幸运的是,自定义视图是!您可以按照之前的建议进行操作,但我通常会避免创建自定义页面,而是创建一个具有自己的内容属性的自定义视图。
编辑:
这些术语可能会与 Xamarin 窗体特别混淆,特别是如果您不熟悉 MVVM 和 Xamarin 窗体,和/或已从其他平台上开发。
Xamarin Forms 所指的View
在其他平台上更常被称为Control
。在使用像Prism这样的MVVM框架时,这尤其令人困惑,因为我们的MVVMViews
实际上是Xamarin FormsPages
。
虽然我们需要不时创建自定义类型的页面,但通常情况下,我们只是实现一些页面类型。例如,假设我有一个页面,我将用于登录页面:
登录页面.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
Title="{Binding Title}"
x:Class="MyAwesomeApp.Views.LoginPage">
<Grid BackgroundColor="{DynamicResource primary}">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="3*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.Resources>
<ResourceDictionary>
<Style TargetType="StackLayout">
<Setter Property="BackgroundColor" Value="White" />
<Setter Property="VerticalOptions" Value="FillAndExpand" />
</Style>
<Style TargetType="Entry">
<Setter Property="Margin" Value="40,10" />
</Style>
<Style TargetType="Button">
<Setter Property="Margin" Value="20" />
<Setter Property="BackgroundColor" Value="{DynamicResource primaryDark}" />
<Setter Property="TextColor" Value="White" />
<Setter Property="BorderRadius" Value="5" />
<Setter Property="BorderWidth" Value="1" />
<Setter Property="BorderColor" Value="Black" />
</Style>
</ResourceDictionary>
</Grid.Resources>
<Image Source="logo.png"
Aspect="AspectFit"
HorizontalOptions="Center"
VerticalOptions="Center" />
<StackLayout Grid.Row="1">
<Entry Text="{Binding UserName}"
Placeholder="Enter your username"
x:Name="userNameEntry"
VerticalOptions="EndAndExpand" />
<Entry Text="{Binding Password}"
Placeholder="Enter your password"
IsPassword="True"
x:Name="passwordEntry"
VerticalOptions="StartAndExpand" />
<Button Text="Submit"
Command="{Binding LoginCommand}" />
</StackLayout>
</Grid>
</ContentPage>
LoginPage.xaml.cs
public partial class LoginPage
{
public LoginPage()
{
InitializeComponent();
}
}
虽然 XAML 中有很多内容,但这只是一个内容页。它绝不是自定义页面。您会注意到此处背后的代码中绝对没有任何内容。例如,如果用户点击键盘上的 Done/Enter 并转到下一个字段或调用按钮单击,我可能会创建一些事件处理程序,但这仍然不会使其成为自定义页面。
有关"自定义页面"的示例,您可以查看XLabs ExtendedTabbedPage。您会注意到的一件事是,他们的 TabbedPage 版本上有几个新属性。当然,他们的页面只能因为渲染器而工作
坚持我已经展示的示例,假设我们想采用我在页面中创建的登录布局,并希望能够跨项目重用它,或者在我的应用程序的不同页面上重复使用它。然后我想做这样的事情:
LoginView.xaml
<?xml version="1.0" encoding="UTF-8"?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="{DynamicResource primary}"
x:Name="grid"
x:Class="MyAwesomeApp.Controls.LoginView">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="3*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.Resources>
<ResourceDictionary>
<Style TargetType="StackLayout">
<Setter Property="BackgroundColor" Value="White" />
<Setter Property="VerticalOptions" Value="FillAndExpand" />
</Style>
<Style TargetType="Entry">
<Setter Property="Margin" Value="40,10" />
</Style>
<Style TargetType="Button">
<Setter Property="Margin" Value="20" />
<Setter Property="BackgroundColor" Value="{DynamicResource primaryDark}" />
<Setter Property="TextColor" Value="White" />
<Setter Property="BorderRadius" Value="5" />
<Setter Property="BorderWidth" Value="1" />
<Setter Property="BorderColor" Value="Black" />
</Style>
</ResourceDictionary>
</Grid.Resources>
<Image Source="logo.png"
Aspect="AspectFit"
HorizontalOptions="Center"
VerticalOptions="Center" />
<StackLayout Grid.Row="1" BindingContext="{x:Reference grid}">
<Entry Text="{Binding UserName}"
Placeholder="Enter your username"
x:Name="userNameEntry"
VerticalOptions="EndAndExpand" />
<Entry Text="{Binding Password}"
Placeholder="Enter your password"
IsPassword="True"
x:Name="passwordEntry"
VerticalOptions="StartAndExpand" />
<Button Text="Submit"
Command="{Binding LoginCommand}" />
</StackLayout>
</Grid>
LoginView.xaml.cs
public partial class LoginView : Grid
{
public static readonly BindableProperty UserNameProperty =
BindableProperty.Create(nameof(UserName), typeof(string), typeof(LoginView), string.Empty);
public static readonly BindableProperty PasswordProperty =
BindableProperty.Create(nameof(Password), typeof(string), typeof(LoginView), string.Empty);
public static readonly BindableProperty LoginCommandProperty =
BindableProperty.Create(nameof(LoginCommand), typeof(ICommand), typeof(LoginView), null);
public LoginView()
{
InitializeComponent();
}
public string UserName
{
get { return (string)GetValue(UserNameProperty); }
set { SetValue(UserNameProperty,value); }
}
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public ICommand LoginCommand
{
get { return (ICommand)GetValue(LoginCommandProperty); }
set { SetValue(LoginCommandProperty, value); }
}
}
折射登录页面.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MyAwesomeApp.Controls"
Title="{Binding Title}"
x:Class="MyAwesomeApp.Views.LoginPage">
<controls:LoginView UserName="{Binding UserName}"
Password="{Binding Password}"
LoginCommand="{Binding LoginCommand}" />
</ContentPage>
您最终会得到的LoginView
实际上是一个自定义控件。虽然它可能来自网格,但您通常并不关心我如何决定创建布局......你只关心我给你一些控制权,这些控制权具有可以附加到的UserName
和Password
属性以及一些可以执行的LoginCommand
。正是这种固有的差异实际上使其成为自定义视图。
我有一种方法。不完全是你想要的,但可以给你思考的食物。您可以使用SomeContent
属性创建SomeBaseContentPage
:
public View SomeContent
{
set
{
someGrid.Children.Add(value);
}
}
然后从SomeBaseContentPage
中获取SomeContentPageA
,XAML
将您的特定内容放入财产<SomeBaseContentPage.SomeContent>