首页
视频
资源
登录
原
Xamarin.Forms 导航栏 Navigation (三)
6978
人阅读
2022/4/7 17:10
总访问:
2592194
评论:
0
收藏:
0
手机
分类:
.net后台框架
![](https://img.tnblog.net/arcimg/hb/59e2f99dba0340d09e3ea49cc983167f.png) >#Xamarin.Forms 导航栏 Navigation (三) [TOC] ##添加导航栏 tn2>一个常规的App是由多个Page组成的,出现多个Page就会涉及页面跳转问题。Xamarin.Forms页面之间的跳转通过Navigation Stack管理Page,如页面A跳转到页面B时,会将B压入栈定,此时页面B成为活动页面,执行Back操作时,页面B从栈定推出使页面A重新变为活动页面。每个应用程序都有一个特殊页作为应用程序的入口(main page, or the home page, or the start page),Xamarin.Forms中由App的MainPage属性设置。 ```csharp public partial class App : Application { public App() { InitializeComponent(); MainPage = new NavigationPage(new MainPage()); } } ``` ![](https://img.tnblog.net/arcimg/hb/aabd186fdfb3496689464f6fa862f139.png) ## 添加新页面 tn2>我们希望通过上一篇文章所选的集合子选项,弹出一个新的页面。 首先我们先添加一个新的页面`DetailPage.xaml`。 创建一个显示我选中内容的`Label`,并且通过设置`VerticalOptions`属性值为`CenterAndExpand`来进行垂直居中,然后通过设置`HorizontalOptions`属性来进行水平居中;还创建一个`Dismiss`按钮用于关闭当前的页面,在这里呢我让`Label`的`Text`属性绑定了提供数据的`DetailPageViewModel.NoteText`属性,`Dismiss`按钮的点击事件绑定了`DetailPageViewModel.DismissPageCommand`命令。 ```xml <?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:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="FirstApp.DetailPage"> <ContentPage.Content> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height=".2*" /> </Grid.RowDefinitions> <Label Text="{Binding NoteText}" FontSize="Title" Grid.Row="0" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" /> <Button Grid.Row="1" Text="Dismiss" Command="{Binding DismissPageCommand}" /> </Grid> </ContentPage.Content> </ContentPage> ``` tn2>接着我们来查看`DetailPageViewModel`数据源的实体定义。`DetailPageViewModel`同样实现了`INotifyPropertyChanged`接口,并创建了一个`NoteText`属性用于显示所选择的内容值,`DismissPageCommand`通过`await Application.Current.MainPage.Navigation.PopModalAsync();`用于当前用户界面退出页面栈达到一个退出当前页面的功能。 ```csharp public class DetailPageViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public DetailPageViewModel(string note) { DismissPageCommand = new Command(async () => { await Application.Current.MainPage.Navigation.PopModalAsync(); }); NoteText = note; } string noteText; public string NoteText { get => noteText; set { noteText = value; var args = new PropertyChangedEventArgs(nameof(NoteText)); PropertyChanged?.Invoke(this, args); } } public Command DismissPageCommand { get; } } ``` tn2>在我们首页所绑定的数据源`MainPageViewModel`类中,当前集合中所选择文本定义`SelectedNote`属性。以及定义用户界面所选择集合子选项所触发的`SelectedNoteChangedCommand`命令。在触发命令时,我们将创建一个新的页面`DetailPage`,并提供我们所选的子选项内容来创建数据源`DetailPageViewModel`,通过`detailPage.BindingContext`来绑定`DetailPage`所需要的数据。最后通过`await Application.Current.MainPage.Navigation.PushModalAsync`来将这个新的页面压入页面栈顶呈现给用户。 ```csharp public class MainPageViewModel : INotifyPropertyChanged { public Command SelectedNoteChangedCommand { get; } string selectedNote; public string SelectedNote { get => selectedNote; set { selectedNote = value; var args = new PropertyChangedEventArgs(nameof(SelectedNote)); PropertyChanged?.Invoke(this, args); } } public MainPageViewModel() { SelectedNoteChangedCommand = new Command(async ()=> { //创建一个新的页面 var detailVM = new DetailPageViewModel(SelectedNote); var detailPage = new DetailPage(); detailPage.BindingContext = detailVM; //向应用端推送页面 await Application.Current.MainPage.Navigation.PushModalAsync(detailPage); }); EraseCommand = new Command(() => { TheNote = string.Empty; }); SaveCommand = new Command(() => { AllNotes.Add(TheNote); TheNote = string.Empty; }); } public ObservableCollection<string> AllNotes { get; set; } = new ObservableCollection<string>(); public event PropertyChangedEventHandler PropertyChanged; string theNote; public string TheNote { get => theNote; set { theNote = value; var args = new PropertyChangedEventArgs(nameof(TheNote)); PropertyChanged?.Invoke(this, args); } } public Command SaveCommand { get; } public Command EraseCommand { get; } } ``` tn2>接着我们需要在前端绑定好我们相关的定义。 ```xml <?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:local="clr-namespace:FirstApp" x:Class="FirstApp.MainPage"> <ContentPage.BindingContext> <local:MainPageViewModel/> </ContentPage.BindingContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="2*"/> <RowDefinition Height=".5*"/> <RowDefinition Height="2*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Image Source="logo_xamarin" BackgroundColor="PowderBlue" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" /> <Editor Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Placeholder="Enter Note Here" Text="{Binding TheNote}" /> <Button Grid.Row="2" Grid.Column="0" Text="Save" Command="{Binding SaveCommand}" /> <Button Grid.Row="2" Grid.Column="1" Text="Erase" Command="{Binding EraseCommand}" /> <CollectionView ItemsSource="{Binding AllNotes}" SelectionMode="Single" SelectedItem="{Binding SelectedNote}" SelectionChangedCommand="{Binding SelectedNoteChangedCommand}" Grid.Row="3" Grid.ColumnSpan="2" Grid.Column="0"> <CollectionView.ItemTemplate> <DataTemplate> <StackLayout Padding="10,10"> <Frame> <Label Text="{Binding .}" FontSize="Title"/> </Frame> </StackLayout> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </Grid> </ContentPage> ``` ![](https://img.tnblog.net/arcimg/hb/4763bc2ea46b48ec9dea25768520a853.png) ![](https://img.tnblog.net/arcimg/hb/ce6852f3d6534e46aae2d345b557eb1d.png) ![](https://img.tnblog.net/arcimg/hb/f124aab8bc3b4b0e869e5781e17cf226.png) ## Xamarin.Forms Navigation tn2>Xamarin.Forms 提供许多不同的页面导航体验,具体取决于所使用的页面类型。 ![](https://img.tnblog.net/arcimg/hb/8083e7dba19849789f9d2a7d35033742.png) tn2>目前我们使用的是`NavigationPage`分层导航类型。 >### 分层导航 tn2>该类NavigationPage提供分层导航体验,用户可以根据需要在页面中向前和向后导航。该类将导航实现为Page对象的后进先出 (LIFO) 堆栈。通过Push可以推送到页面栈顶端,通过Pop方法可以退出页面栈顶端。 ![](https://img.tnblog.net/arcimg/hb/32f1a585a0d645d8a70bd99896712c87.gif) >### 创建根页面 tn2>添加到导航堆栈的第一个页面称为应用程序的根页面,我们在添加导航栏时讲到了,以下代码示例显示了这是如何完成的: ```csharp public App () { MainPage = new NavigationPage(new MainPage()); } ``` tn2>这会导致`MainPage`ContentPage实例被推送到导航堆栈上,在那里它成为应用程序的活动页面和根页面。 >### 将页面推送到导航堆栈 tn2>要导航到`Page2Xaml`,需要在当前页面PushAsync的属性上调用方法Navigation,如以下代码示例所示: ```csharp await Navigation.PushAsync(new Page2Xaml()); # 全局调用 await Application.Current.MainPage.Navigation.PushAsync(new Page2Xaml()); ``` tn2>调用该PushAsync方法时,会发生以下事件: -- 页面调用调用PushAsync了它的`OnDisappearing`事件。 -- 被导航到的页面`OnAppearing`调用了它的事件。 | 事件名 | 描述 | | ------------ | ------------ | | `OnDisappearing` | 当前页面被覆盖时,页面所触发的事件。 | | `OnAppearing` | 当前页面被覆盖时,显示下一个页面之前所触发的事件。 | ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } protected override void OnAppearing() { base.OnAppearing(); } protected override void OnDisappearing() { base.OnDisappearing(); } } ``` >### 从导航堆栈中退出页面 tn2>活动页面可以通过按下设备上的后退按钮从导航堆栈中弹出,无论这是设备上的物理按钮还是屏幕按钮。 要以编程方式返回原始页面,`Page2Xaml`实例必须调用该`PopAsync`方法,如以下代码示例所示: ```csharp await Navigation.PopAsync(); # 全局调用 await Application.Current.MainPage.Navigation.PopAsync(); ``` tn2>这会从导航堆栈中删除 Page2Xaml 实例,而使最顶层的页成为活动页。 调用 PopAsync 方法后,会发生以下事件: 调用 PopAsync 的页面会调用其 `OnDisappearing` 事件。 要返回到的页面会调用其 `OnAppearing` 事件。 PopAsync 任务返回。 tn>当然它们都还有一个构造`PopAsync(Boolean)`与`PushAsync(Boolean)`,这个可以以**动画**的方式进行删除。 >### 关于不同的导航进行退出与呈现的区别 | 方法 | 描述 | | ------------ | ------------ | | `PushAsync` | 显示某个页面 | | `PopAsync` | 退出当前页面 | | `PushModalAsync` | 以模态的方式显示某个页面(相当于以弹出的页面为主) | | `PopModalAsync` | 退出当前模态页面 | | `PopToRootAsync` | 退出主页 | | `RemovePage` | 删除某个页面 | >### 在导航栏中显示滚动条 tn2>任何 `Xamarin.Forms View` 中可以显示在导航栏 NavigationPage 中。 这是通过将 `NavigationPage.TitleView` 附加属性设置为 `View` 来实现的。 此附加属性可以在任何 `Page` 上设置,当 `Page` 被推送到 `NavigationPage` 上后,`NavigationPage` 会遵守属性的值。 ```csharp <?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:local="clr-namespace:FirstApp" x:Class="FirstApp.MainPage"> <NavigationPage.TitleView> <Slider HeightRequest="44" WidthRequest="300" /> </NavigationPage.TitleView> .... </ContentPage> ``` tn2>下面是等效 C# 代码: ```csharp public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); var titleView = new Slider { HeightRequest = 44, WidthRequest = 300 }; NavigationPage.SetTitleView(this, titleView); } protected override void OnAppearing() { base.OnAppearing(); } protected override void OnDisappearing() { base.OnDisappearing(); } } ``` ![](https://img.tnblog.net/arcimg/hb/16778f41bb6d40018b5f145fedba472a.png)
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
👈{{preArticle.title}}
👉{{nextArticle.title}}
评价
{{titleitem}}
{{titleitem}}
{{item.content}}
{{titleitem}}
{{titleitem}}
{{item.content}}
尘叶心繁
这一世以无限游戏为使命!
博主信息
排名
6
文章
6
粉丝
16
评论
8
文章类别
.net后台框架
168篇
linux
17篇
linux中cve
1篇
windows中cve
0篇
资源分享
10篇
Win32
3篇
前端
28篇
传说中的c
4篇
Xamarin
9篇
docker
15篇
容器编排
101篇
grpc
4篇
Go
15篇
yaml模板
1篇
理论
2篇
更多
Sqlserver
4篇
云产品
39篇
git
3篇
Unity
1篇
考证
2篇
RabbitMq
23篇
Harbor
1篇
Ansible
8篇
Jenkins
17篇
Vue
1篇
Ids4
18篇
istio
1篇
架构
2篇
网络
7篇
windbg
4篇
AI
18篇
threejs
2篇
人物
1篇
嵌入式
2篇
python
13篇
HuggingFace
8篇
pytorch
9篇
opencv
6篇
最新文章
最新评价
{{item.articleTitle}}
{{item.blogName}}
:
{{item.content}}
关于我们
ICP备案 :
渝ICP备18016597号-1
网站信息:
2018-2024
TNBLOG.NET
技术交流:
群号656732739
联系我们:
contact@tnblog.net
欢迎加群
欢迎加群交流技术