tnblog
首页
视频
资源
登录

Xamarin.Forms 导航栏 Navigation (三)

8786人阅读 2022/4/7 17:10 总访问:3467189 评论:0 收藏:0 手机
分类: .net后台框架

Xamarin.Forms 导航栏 Navigation (三)

添加导航栏


一个常规的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属性设置。

  1. public partial class App : Application
  2. {
  3. public App()
  4. {
  5. InitializeComponent();
  6. MainPage = new NavigationPage(new MainPage());
  7. }
  8. }

添加新页面


我们希望通过上一篇文章所选的集合子选项,弹出一个新的页面。
首先我们先添加一个新的页面DetailPage.xaml
创建一个显示我选中内容的Label,并且通过设置VerticalOptions属性值为CenterAndExpand来进行垂直居中,然后通过设置HorizontalOptions属性来进行水平居中;还创建一个Dismiss按钮用于关闭当前的页面,在这里呢我让LabelText属性绑定了提供数据的DetailPageViewModel.NoteText属性,Dismiss按钮的点击事件绑定了DetailPageViewModel.DismissPageCommand命令。

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  4. xmlns:d="http://xamarin.com/schemas/2014/forms/design"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. mc:Ignorable="d"
  7. x:Class="FirstApp.DetailPage">
  8. <ContentPage.Content>
  9. <Grid>
  10. <Grid.RowDefinitions>
  11. <RowDefinition Height="*" />
  12. <RowDefinition Height=".2*" />
  13. </Grid.RowDefinitions>
  14. <Label Text="{Binding NoteText}" FontSize="Title" Grid.Row="0" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" />
  15. <Button Grid.Row="1" Text="Dismiss" Command="{Binding DismissPageCommand}" />
  16. </Grid>
  17. </ContentPage.Content>
  18. </ContentPage>


接着我们来查看DetailPageViewModel数据源的实体定义。DetailPageViewModel同样实现了INotifyPropertyChanged接口,并创建了一个NoteText属性用于显示所选择的内容值,DismissPageCommand通过await Application.Current.MainPage.Navigation.PopModalAsync();用于当前用户界面退出页面栈达到一个退出当前页面的功能。

  1. public class DetailPageViewModel : INotifyPropertyChanged
  2. {
  3. public event PropertyChangedEventHandler PropertyChanged;
  4. public DetailPageViewModel(string note)
  5. {
  6. DismissPageCommand = new Command(async () => {
  7. await Application.Current.MainPage.Navigation.PopModalAsync();
  8. });
  9. NoteText = note;
  10. }
  11. string noteText;
  12. public string NoteText
  13. {
  14. get => noteText;
  15. set {
  16. noteText = value;
  17. var args = new PropertyChangedEventArgs(nameof(NoteText));
  18. PropertyChanged?.Invoke(this, args);
  19. }
  20. }
  21. public Command DismissPageCommand { get; }
  22. }


在我们首页所绑定的数据源MainPageViewModel类中,当前集合中所选择文本定义SelectedNote属性。以及定义用户界面所选择集合子选项所触发的SelectedNoteChangedCommand命令。在触发命令时,我们将创建一个新的页面DetailPage,并提供我们所选的子选项内容来创建数据源DetailPageViewModel,通过detailPage.BindingContext来绑定DetailPage所需要的数据。最后通过await Application.Current.MainPage.Navigation.PushModalAsync来将这个新的页面压入页面栈顶呈现给用户。

  1. public class MainPageViewModel : INotifyPropertyChanged
  2. {
  3. public Command SelectedNoteChangedCommand { get; }
  4. string selectedNote;
  5. public string SelectedNote
  6. {
  7. get => selectedNote;
  8. set
  9. {
  10. selectedNote = value;
  11. var args = new PropertyChangedEventArgs(nameof(SelectedNote));
  12. PropertyChanged?.Invoke(this, args);
  13. }
  14. }
  15. public MainPageViewModel()
  16. {
  17. SelectedNoteChangedCommand = new Command(async ()=> {
  18. //创建一个新的页面
  19. var detailVM = new DetailPageViewModel(SelectedNote);
  20. var detailPage = new DetailPage();
  21. detailPage.BindingContext = detailVM;
  22. //向应用端推送页面
  23. await Application.Current.MainPage.Navigation.PushModalAsync(detailPage);
  24. });
  25. EraseCommand = new Command(() => {
  26. TheNote = string.Empty;
  27. });
  28. SaveCommand = new Command(() => {
  29. AllNotes.Add(TheNote);
  30. TheNote = string.Empty;
  31. });
  32. }
  33. public ObservableCollection<string> AllNotes { get; set; } = new ObservableCollection<string>();
  34. public event PropertyChangedEventHandler PropertyChanged;
  35. string theNote;
  36. public string TheNote
  37. {
  38. get => theNote;
  39. set
  40. {
  41. theNote = value;
  42. var args = new PropertyChangedEventArgs(nameof(TheNote));
  43. PropertyChanged?.Invoke(this, args);
  44. }
  45. }
  46. public Command SaveCommand { get; }
  47. public Command EraseCommand { get; }
  48. }


接着我们需要在前端绑定好我们相关的定义。

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  4. xmlns:local="clr-namespace:FirstApp"
  5. x:Class="FirstApp.MainPage">
  6. <ContentPage.BindingContext>
  7. <local:MainPageViewModel/>
  8. </ContentPage.BindingContext>
  9. <Grid>
  10. <Grid.RowDefinitions>
  11. <RowDefinition Height="*"/>
  12. <RowDefinition Height="2*"/>
  13. <RowDefinition Height=".5*"/>
  14. <RowDefinition Height="2*"/>
  15. </Grid.RowDefinitions>
  16. <Grid.ColumnDefinitions>
  17. <ColumnDefinition Width="*"/>
  18. <ColumnDefinition Width="*"/>
  19. </Grid.ColumnDefinitions>
  20. <Image Source="logo_xamarin" BackgroundColor="PowderBlue"
  21. Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" />
  22. <Editor Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Placeholder="Enter Note Here" Text="{Binding TheNote}" />
  23. <Button Grid.Row="2" Grid.Column="0" Text="Save" Command="{Binding SaveCommand}" />
  24. <Button Grid.Row="2" Grid.Column="1" Text="Erase" Command="{Binding EraseCommand}" />
  25. <CollectionView
  26. ItemsSource="{Binding AllNotes}"
  27. SelectionMode="Single"
  28. SelectedItem="{Binding SelectedNote}"
  29. SelectionChangedCommand="{Binding SelectedNoteChangedCommand}"
  30. Grid.Row="3" Grid.ColumnSpan="2" Grid.Column="0">
  31. <CollectionView.ItemTemplate>
  32. <DataTemplate>
  33. <StackLayout Padding="10,10">
  34. <Frame>
  35. <Label Text="{Binding .}" FontSize="Title"/>
  36. </Frame>
  37. </StackLayout>
  38. </DataTemplate>
  39. </CollectionView.ItemTemplate>
  40. </CollectionView>
  41. </Grid>
  42. </ContentPage>

Xamarin.Forms Navigation


Xamarin.Forms 提供许多不同的页面导航体验,具体取决于所使用的页面类型。


目前我们使用的是NavigationPage分层导航类型。

分层导航


该类NavigationPage提供分层导航体验,用户可以根据需要在页面中向前和向后导航。该类将导航实现为Page对象的后进先出 (LIFO) 堆栈。通过Push可以推送到页面栈顶端,通过Pop方法可以退出页面栈顶端。

创建根页面


添加到导航堆栈的第一个页面称为应用程序的根页面,我们在添加导航栏时讲到了,以下代码示例显示了这是如何完成的:

  1. public App ()
  2. {
  3. MainPage = new NavigationPage(new MainPage());
  4. }


这会导致MainPageContentPage实例被推送到导航堆栈上,在那里它成为应用程序的活动页面和根页面。

将页面推送到导航堆栈


要导航到Page2Xaml,需要在当前页面PushAsync的属性上调用方法Navigation,如以下代码示例所示:

  1. await Navigation.PushAsync(new Page2Xaml());
  2. # 全局调用
  3. await Application.Current.MainPage.Navigation.PushAsync(new Page2Xaml());


调用该PushAsync方法时,会发生以下事件:
— 页面调用调用PushAsync了它的OnDisappearing事件。
— 被导航到的页面OnAppearing调用了它的事件。

事件名 描述
OnDisappearing 当前页面被覆盖时,页面所触发的事件。
OnAppearing 当前页面被覆盖时,显示下一个页面之前所触发的事件。
  1. public partial class MainPage : ContentPage
  2. {
  3. public MainPage()
  4. {
  5. InitializeComponent();
  6. }
  7. protected override void OnAppearing()
  8. {
  9. base.OnAppearing();
  10. }
  11. protected override void OnDisappearing()
  12. {
  13. base.OnDisappearing();
  14. }
  15. }

从导航堆栈中退出页面


活动页面可以通过按下设备上的后退按钮从导航堆栈中弹出,无论这是设备上的物理按钮还是屏幕按钮。
要以编程方式返回原始页面,Page2Xaml实例必须调用该PopAsync方法,如以下代码示例所示:

  1. await Navigation.PopAsync();
  2. # 全局调用
  3. await Application.Current.MainPage.Navigation.PopAsync();


这会从导航堆栈中删除 Page2Xaml 实例,而使最顶层的页成为活动页。 调用 PopAsync 方法后,会发生以下事件:
调用 PopAsync 的页面会调用其 OnDisappearing 事件。
要返回到的页面会调用其 OnAppearing 事件。
PopAsync 任务返回。

当然它们都还有一个构造PopAsync(Boolean)PushAsync(Boolean),这个可以以动画的方式进行删除。

关于不同的导航进行退出与呈现的区别

方法 描述
PushAsync 显示某个页面
PopAsync 退出当前页面
PushModalAsync 以模态的方式显示某个页面(相当于以弹出的页面为主)
PopModalAsync 退出当前模态页面
PopToRootAsync 退出主页
RemovePage 删除某个页面

在导航栏中显示滚动条


任何 Xamarin.Forms View 中可以显示在导航栏 NavigationPage 中。 这是通过将 NavigationPage.TitleView 附加属性设置为 View 来实现的。 此附加属性可以在任何 Page 上设置,当 Page 被推送到 NavigationPage 上后,NavigationPage 会遵守属性的值。

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  4. xmlns:local="clr-namespace:FirstApp"
  5. x:Class="FirstApp.MainPage">
  6. <NavigationPage.TitleView>
  7. <Slider HeightRequest="44" WidthRequest="300" />
  8. </NavigationPage.TitleView>
  9. ....
  10. </ContentPage>


下面是等效 C# 代码:

  1. public partial class MainPage : ContentPage
  2. {
  3. public MainPage()
  4. {
  5. InitializeComponent();
  6. var titleView = new Slider { HeightRequest = 44, WidthRequest = 300 };
  7. NavigationPage.SetTitleView(this, titleView);
  8. }
  9. protected override void OnAppearing()
  10. {
  11. base.OnAppearing();
  12. }
  13. protected override void OnDisappearing()
  14. {
  15. base.OnDisappearing();
  16. }
  17. }


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

评价

如何解决导航栏过长而滑不动问题?

这是导航栏文章本来可以滑动的,但编写了加载时间后就划不动了,然后滑动文章呈现出这种效果:这该如何解决?

Android 获取导航栏的高度

获取Android手机屏幕的高度/** *获取状态栏高度 * *@paramcontext上下文 *@return高度 */publicstaticintgetStatusBar...

editormdmarkdown 自定义导航栏按钮

editormd,markdown 自定义导航栏按钮可以通过修改源代码来实现,但是没有必要那么麻烦。 editormd本身就有增加自定义按钮...

uni-app导航栏搜索框,导航栏按钮

官网的导航栏文档:https://ext.dcloud.net.cn/plugin?id=1765往下面翻就可以看到搜索栏的文档 导航栏带搜索框:按照文档...

uni-app标题导航栏官方例子

例子位置: 源码: &lt;template&gt; &lt;view class=&quot;page&quot;&gt; &lt;swiper indicator-dots=&q...

uni-app transparent模式系统导航栏透明

代码:{ &quot;path&quot;:&quot;pages/home/devices-info/shop-detail&quot;, &quot;style&quot;:{ &quot;navigationBa...

uni-app导航栏搜索框让默认的搜索文章搜索图标距离左边

uni-app导航栏搜索框让默认的搜索文章搜索图标距离左边很简单有一个属性可以设置,&quot;align&quot;:&quot;left&quot;即可...

uni-app自定义导航栏文档,自定义导航栏按钮文档

自定义导航栏相关https://uniapp.dcloud.io/collocation/pages?id=app-titlnview 导航栏就是在pages里边页面配置的app-pl...

uni-app自定义导航栏按钮

自定义导航栏按钮文档https://uniapp.dcloud.io/collocation/pages?id=app-titlenview-buttons 按钮类型默认提供了这些,...

使用自定义导航栏

导航栏作为常用组件有做简单封装,当然你也可以直接复制代码结构自己修改,达到个性化目的。 `App.vue`获得系统信息 ``...

js获取当前地址栏的地址与端口。js获取当前导航栏ip和端口。js获取地址栏参数。vue获取带的地址栏参数

[TOC]js获取当前地址栏的地址与端口。js获取当前导航栏ip和端口let API_HOST = window.location.protocol+&quot;//&quot;+w...

这样学英语个月超过你过去学

本文作者三年间从四级勉强及格到高级口译笔试210,口试232。找工作面试时给其口试的老外考官听了一分钟就说你的英语不用考...

行代码 人民币金额大写转换

publicstaticStringConvertToChinese(Decimalnumber) { vars=number.ToString(&quot;#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H...

C.Net 配合小程序实现经过第方服务器中转文件

某些时候,微信小程序前段上传文件的时候需要经过第三方服务器再将文件上传到客户的服务器;操作如下:1:(小程序内向中端服...

分钟快速复习MVC知识

读这篇文章不意味着你一定要去并且能搞定MVC面试。这篇文章的目的是在面试之前让你快速复习MVC知识。什么是MVC (模型 视图 ...
这一世以无限游戏为使命!
排名
2
文章
634
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 : 好是好,这个对效率影响大不大哇,效率高不高
ASP.NET Core 服务注册生命周期
剑轩 : http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术