第二十四章:页面导航(六)

简介: 制作导航菜单如果您的应用程序包含各种不同但在架构上相同的页面,所有这些页面都可以从主页导航,那么您可能有兴趣构建有时称为导航菜单的页面。 这是一个菜单,其中每个条目都是特定的页面类型。ViewGalleryType程序旨在演示Xamarin.Forms中的所有View类。

制作导航菜单
如果您的应用程序包含各种不同但在架构上相同的页面,所有这些页面都可以从主页导航,那么您可能有兴趣构建有时称为导航菜单的页面。 这是一个菜单,其中每个条目都是特定的页面类型。
ViewGalleryType程序旨在演示Xamarin.Forms中的所有View类。 它包含一个主页和一个页面,用于Xamarin.Forms中的每个可实例化类,它们来自View而不是Layout,但Map和OpenGLView除外。 这是18个类和18个ContentPage衍生产品,加上主页。 (项目名称上的类型后缀的原因很快就会显现出来。)
这18个页面类都存储在Portable Class Library中名为ViewPages的文件夹中。 这是一个例子:SliderPage.xaml。 它只是一个标签绑定到Value属性的Slider:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ViewGalleryType.SliderPage"
             Title="Slider">
    <StackLayout Padding="10, 0">
        <Slider x:Name="slider"
                VerticalOptions="CenterAndExpand" />
 
        <Label Text="{Binding Source={x:Reference slider},
                              Path=Value,
                              StringFormat='The Slider value is {0}'}"
               VerticalOptions="CenterAndExpand"
               HorizontalAlignment="Center" />
    </StackLayout>
</ContentPage> 

其他17个是相似的。 有些页面在代码隐藏文件中有一些代码,但大多数只是调用InitializeComponent。
此外,ViewGalleryType项目有一个名为Images的文件夹,其中包含18个位图,每个View衍生的名称都延伸到几乎填满位图的表面。 这些位图由Windows Presentation Foundation程序生成,并在项目中标记为EmbeddedResource。 该项目还包含第13章“嵌入式资源”一节中描述的ImageResourceExtension类,以引用XAML文件中的位图。
主页名为ViewGalleryTypePage。 它在表的六个不同部分组装了18个ImageCell元素:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ViewGalleryType;assembly=ViewGalleryType"
             x:Class="ViewGalleryType.ViewGalleryTypePage"
             Title="View Gallery">
    <TableView Intent="Menu">
        <TableRoot>
            <TableSection Title="Presentation Views">
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Label.png}"
                           Text="Display text"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:LabelPage}" />
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Image.png}"
                           Text="Display a bitmap"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:ImagePage}" />
 
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.BoxView.png}"
                           Text="Display a block"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:BoxViewPage}" />
 
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.WebView.png}"
                           Text="Display a web site"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:WebViewPage}" />
            </TableSection>
            <TableSection Title="Command Views">
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Button.png}"
                           Text="Initiate a command"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:ButtonPage}" />
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.SearchBar.png}"
                           Text="Initiate a text search"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:SearchBarPage}" />
            </TableSection>
            <TableSection Title="Data-Type Views">
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Slider.png}"
                           Text="Range of doubles"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:SliderPage}" />
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.Stepper.png}"
                           Text="Discrete doubles"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:StepperPage}" />
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Switch.png}"
                           Text="Select true or false"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:SwitchPage}" />
                 
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.DatePicker.png}"
                           Text="Select a date"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:DatePickerPage}" />
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.TimePicker.png}"
                           Text="Select a time"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:TimePickerPage}" />
            </TableSection>
            <TableSection Title="Text-Editing Views">
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Entry.png}"
                           Text="Edit a single line"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:EntryPage}" />
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Editor.png}"
                           Text="Edit a paragraph"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:EditorPage}" />
            </TableSection>
            <TableSection Title="Activity Indicator Views">
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.ActivityIndicator.png}"
                           Text="Show activity"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:ActivityIndicatorPage}" />
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.ProgressBar.png}"
                           Text="Show progress"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:ProgressBarPage}" />
            </TableSection>
            <TableSection Title="Collection Views">
                <ImageCell ImageSource="{local:ImageResource ViewGalleryType.Images.Picker.png}"
                           Text="Pick item from list"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:PickerPage}" />
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.ListView.png}"
                           Text="Show a collection"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:ListViewPage}" />
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryType.Images.TableView.png}"
                           Text="Show form or menu"
                           Command="{Binding NavigateCommand}"
                           CommandParameter="{x:Type local:TableViewPage}" />
            </TableSection>
        </TableRoot>
    </TableView>
</ContentPage>

每个ImageCell都引用一个指示视图名称的位图和一个简要描述视图的Text属性。 ImageCell的Command属性绑定到ICommand对象
在代码隐藏文件中实现,CommandParameter是一个引用其中一个页面类的x:Type标记扩展。 您可能还记得,x:Type标记扩展是C#typeof运算符的XAML等效项,并且每个CommandParameter都是Type类型。
以下是三个平台上主页的外观:
2019_04_18_213330
代码隐藏文件定义每个ImageCell在绑定中引用的NavigateCommand属性。 Execute方法实现为lambda函数:它将Type参数(从XAML文件中的CommandParameter设置)传递给Activator.CreateInstance以实例化页面,然后导航到该页面:

public partial class ViewGalleryTypePage : ContentPage
{
    public ViewGalleryTypePage()
    {
        InitializeComponent();
        NavigateCommand = new Command<Type>(async (Type pageType) =>
        {
            Page page = (Page)Activator.CreateInstance(pageType);
            await Navigation.PushAsync(page);
        });
        BindingContext = this;
    }
    public ICommand NavigateCommand { private set; get; }
}

构造函数通过将其BindingContext属性设置为自身来结束,因此XAML文件中的每个ImageCell都可以通过简单的Binding引用NavigateCommand属性。
点击Slider条目(例如)导航到SliderPage:
2019_04_18_213559
返回主页需要使用iOS和Android屏幕上的导航栏或Android和Windows 10 Mobile屏幕上的后退按钮。
每次导航到该页面时都会创建每个页面的新实例,因此SliderPage的这些不同实例当然不会保留您之前设置的Slider的值。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ViewGalleryInst;assembly=ViewGalleryInst"
             x:Class="ViewGalleryInst.ViewGalleryInstPage"
             Title="View Gallery">
    <TableView Intent="Menu">
        <TableRoot>
            <TableSection Title="Presentation Views">
                <ImageCell ImageSource="{local:ImageResource ViewGalleryInst.Images.Label.png}"
                           Text="Display text"
                           Command="{Binding NavigateCommand}">
                    <ImageCell.CommandParameter>
                        <local:LabelPage />
                    </ImageCell.CommandParameter>
                </ImageCell>
                __
                <ImageCell ImageSource=
                           "{local:ImageResource ViewGalleryInst.Images.TableView.png}"
                           Text="Show form or menu"
                           Command="{Binding NavigateCommand}">
                    <ImageCell.CommandParameter>
                        <local:TableViewPage />
                    </ImageCell.CommandParameter>
                 </ImageCell>
            </TableSection>
        </TableRoot>
    </TableView>
</ContentPage>

现在,当您在SliderPage上操作Slider,然后返回到home并再次导航到SliderPage时,Slider将是相同的,因为它是相同的页面实例。
请记住,使用此配置,程序启动时总共会实例化19个页面类,这意味着将解析19个XAML文件,这可能会影响启动性能,并占用大量内存。
此外,在此运行时解析期间找到的XAML文件中的任何错误也将在程序启动时显现。 可能很难准确发现哪个XAML文件存在问题! 在构建一次性实例化多个页面类的程序时,您需要以增量方式添加新类,以确保在继续之前一切正常。
更好的是,完全避免这种技术。 根据需要实例化每个页面,并使用ViewModel保留与页面关联的数据。

目录
相关文章
|
7月前
|
小程序 API
【微信小程序】-- 页面导航 -- 声明式导航(二十二)
【微信小程序】-- 页面导航 -- 声明式导航(二十二)
|
Android开发 索引 iOS开发
第二十四章:页面导航(十七)
像现实生活中的应用程序理想情况下,用户在终止并重新启动应用程序时不应该知道。应用程序体验应该是连续且无缝的。即使程序没有一直运行,一个半月进入的条目从未完成也应该在一周后处于相同的状态。NoteTaker程序允许用户记录由标题和一些文本组成的注释。
548 0
|
XML JSON Android开发
第二十四章:页面导航(十五)
保存和恢复页面状态特别是当您开始使用多页面应用程序时,将应用程序的页面视为数据的主要存储库非常有用,而仅仅是作为底层数据的临时可视化和交互式视图。这里的关键词是暂时的。如果您在用户与之交互时保持基础数据是最新的,那么页面可以显示和消失而不必担心。
656 0
|
JavaScript 前端开发 Android开发
第二十四章:页面导航(十六)
保存和恢复导航堆栈 许多多页面应用程序的页面体系结构比DataTransfer6更复杂,您需要一种通用的方法来保存和恢复整个导航堆栈。此外,您可能希望将导航堆栈的保存与系统方式集成,以保存和恢复每个页面的状态,特别是如果您不使用MVVM。
499 0
|
JavaScript Android开发
第二十四章:页面导航(十四)
切换到ViewModel此时应该很明显,Information类应该真正实现INotifyPropertyChanged。 在DataTransfer5中,Information类已成为InformationViewModel类。
606 0
|
JavaScript Android开发 索引
第二十四章:页面导航(十)
属性和方法调用调用PushAsync或PushModalAsync的页面显然可以直接访问它导航到的类,因此它可以设置属性或调用该页面对象中的方法以将信息传递给它。但是,调用PopAsync或PopModalAsync的页面还有一些工作要做,以确定它返回的页面。
555 0
|
JavaScript Android开发 索引
第二十四章:页面导航(十三)
App类中介在Xamarin.Forms应用程序中,在公共代码项目中执行的第一个代码是通常名为App的类的构造函数,该类派生自Application。 在程序终止之前,此App对象保持不变,并且程序中的任何代码都可以通过静态Application.Current属性使用它。
516 0
|
JavaScript Android开发
第二十四章:页面导航(九)
数据传输模式 多页面应用程序中的页面通常需要共享数据,特别是一页面将信息传递到另一页面。 有时此过程类似于函数调用:当HomePage显示项目列表并导航到DetailPage以显示其中一个项目的详细视图时,HomePage必须将该特定项目传递给DetailPage。
636 0
|
Android开发
第二十四章:页面导航(八)
动态页面生成BuildAPage程序是一个多页面应用程序,但BuildAPage项目只包含一个名为BuildAPageHomePage的页面类。 顾名思义,该程序从代码构造一个新页面,然后导航到它。XAML文件允许您在此构造的页面上指定所需内容: <ContentPage xmlns="http://xamarin.
674 0