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

简介: 操纵导航堆栈有时需要改变正常的面向堆栈的导航流程。例如,假设页面需要来自用户的一些信息,但首先它导航到提供一些指令或免责声明的页面,然后从那里导航到实际获取信息的页面。当用户完成并返回时,您将希望跳过包含说明或免责声明的页面。

操纵导航堆栈
有时需要改变正常的面向堆栈的导航流程。例如,假设页面需要来自用户的一些信息,但首先它导航到提供一些指令或免责声明的页面,然后从那里导航到实际获取信息的页面。当用户完成并返回时,您将希望跳过包含说明或免责声明的页面。该页面应从导航堆栈中删除。
这是一个类似的例子:假设用户正在与获取某些信息的页面进行交互,然后想要返回上一页。但是,程序检测到此信息出现问题,需要在单独的页面上进行扩展讨论。该程序可以将新页面插入导航堆栈以提供该讨论。
或者某个页面序列可能以标记为“转到主页”的按钮结束,并且在导航回主页时可以简单地跳过其间的所有页面。
INavigation接口定义了所有这三种情况的方法。它们被命名为RemovePage,InsertPageBefore和PopToRootAsync。
StackManipulation程序以非常抽象的方式演示了这三种方法。该程序由五个仅代码页面组成,分别名为PageA,PageB,PageBAlternative,PageC和PageD。每个页面都设置其Title属性以标识自身。
PageA有一个导航到PageB的按钮:

public class PageA : ContentPage
{
    public PageA()
    {
        Button button = new Button
        {
            Text = "Go to Page B",
            FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Button)),
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };
        button.Clicked += async (sender, args) =>
        {
            await Navigation.PushAsync(new PageB());
        };
        Title = "Page A";
        Content = new button;
    }
}

PageB类似,只是导航到PageC。 PageBA替代与PageB相同,只是它将自己标识为“Page B Alt”。 PageC有一个按钮可以导航到PageD,而PageD有两个按钮:

public class PageD : ContentPage
{
    public PageD()
    {
        // Create Button to go directly to PageA.
        Button homeButton = new Button
        {
            Text = "Go Directly to Home",
            FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Button)),
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };
        homeButton.Clicked += async (sender, args) =>
        {
            await Navigation.PopToRootAsync();
        };
        // Create Button to swap pages.
        Button swapButton = new Button
        {
            Text = "Swap B and Alt B",
            FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Button)),
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };
        swapButton.Clicked += (sender, args) =>
        {
            IReadOnlyList<Page> navStack = Navigation.NavigationStack;
            Page pageC = navStack[navStack.Count - 2];
            Page existingPageB = navStack[navStack.Count - 3];
            bool isOriginal = existingPageB is PageB;
            Page newPageB = isOriginal ? (Page)new PageBAlternative() : new PageB();
            // Swap the pages.
            Navigation.RemovePage(existingPageB);
            Navigation.InsertPageBefore(newPageB, pageC);
            // Finished: Disable the Button.
            swapButton.IsEnabled = false;
        };
        Title = "Page D";
        Content = new StackLayout
        {
            Children =
            {
                homeButton,
                swapButton
            }
        };
    }
}

标记为Go Directly to Home的按钮具有一个调用PopToRootAsync的Clicked处理程序。 这会导致程序跳回到PageA并有效地清除所有中间页面的导航堆栈。
标记为Swap B和Alt B的按钮稍微复杂一些。 此按钮的Clicked处理程序将PageB替换为导航堆栈中的PageBAlternative(反之亦然),因此当您返回页面时,您将遇到不同的页面B.以下是Clicked处理程序的执行方式:
在单击Button时,NavigationStack有四个索引为0,1,2和3的项。这四个索引对应于PageA(PageB(或PageBA替代),PageC和PageD类型的堆栈中的对象。 处理程序访问NavigationStack以获取这些实际实例:

IReadOnlyList<Page> navStack = Navigation.NavigationStack;
Page pageC = navStack[navStack.Count - 2];
Page existingPageB = navStack[navStack.Count - 3];

现有的Page对象可能是Page或Page Alternative类型,因此创建另一个类型的newPageB对象:

bool isOriginal = existingPageB is PageB;
Page newPageB = isOriginal ? (Page)new PageBAlternative() : new PageB();

接下来的两个语句从导航堆栈中删除existingPageB对象,然后在pageC之前插入newPageB对象,有效地交换页面:

// Swap the pages.
Navigation.RemovePage(existingPageB);
Navigation.InsertPageBefore(newPageB, pageC);

显然,第一次单击此按钮时,existingPageB将是一个PageB对象,newPageB将是一个PageBA替代对象,但您可以返回到PageC或PageBA替代,然后再向前导航到PageD。 再次单击该按钮将使用PageB对象替换PageBAlternative对象。

目录
相关文章
|
1月前
|
小程序
【微信小程序】-- 页面导航 -- 编程式导航(二十三)
【微信小程序】-- 页面导航 -- 编程式导航(二十三)
|
1月前
|
小程序 API
【微信小程序】-- 页面导航 -- 声明式导航(二十二)
【微信小程序】-- 页面导航 -- 声明式导航(二十二)
|
存储 人机交互 UED
网站导航设计方法总结
网站导航设计攻略
908 0
|
Android开发 索引 iOS开发
第二十四章:页面导航(十七)
像现实生活中的应用程序理想情况下,用户在终止并重新启动应用程序时不应该知道。应用程序体验应该是连续且无缝的。即使程序没有一直运行,一个半月进入的条目从未完成也应该在一周后处于相同的状态。NoteTaker程序允许用户记录由标题和一些文本组成的注释。
524 0
|
JavaScript 前端开发 Android开发
第二十四章:页面导航(十六)
保存和恢复导航堆栈 许多多页面应用程序的页面体系结构比DataTransfer6更复杂,您需要一种通用的方法来保存和恢复整个导航堆栈。此外,您可能希望将导航堆栈的保存与系统方式集成,以保存和恢复每个页面的状态,特别是如果您不使用MVVM。
463 0
|
XML JSON Android开发
第二十四章:页面导航(十五)
保存和恢复页面状态特别是当您开始使用多页面应用程序时,将应用程序的页面视为数据的主要存储库非常有用,而仅仅是作为底层数据的临时可视化和交互式视图。这里的关键词是暂时的。如果您在用户与之交互时保持基础数据是最新的,那么页面可以显示和消失而不必担心。
629 0
|
JavaScript Android开发
第二十四章:页面导航(十四)
切换到ViewModel此时应该很明显,Information类应该真正实现INotifyPropertyChanged。 在DataTransfer5中,Information类已成为InformationViewModel类。
570 0
|
JavaScript Android开发 索引
第二十四章:页面导航(十)
属性和方法调用调用PushAsync或PushModalAsync的页面显然可以直接访问它导航到的类,因此它可以设置属性或调用该页面对象中的方法以将信息传递给它。但是,调用PopAsync或PopModalAsync的页面还有一些工作要做,以确定它返回的页面。
523 0
|
JavaScript Android开发
第二十四章:页面导航(九)
数据传输模式 多页面应用程序中的页面通常需要共享数据,特别是一页面将信息传递到另一页面。 有时此过程类似于函数调用:当HomePage显示项目列表并导航到DetailPage以显示其中一个项目的详细视图时,HomePage必须将该特定项目传递给DetailPage。
606 0
|
Android开发 索引
第二十四章:页面导航(十二)
事件在方法调用方法和消息中心通信方法中,信息页面需要知道主页的类型。 如果可以从不同类型的页面调用相同的信息页面,这有时是不合需要的。这个问题的一个解决方案是info类实现一个事件,这就是DataTransfer3中采用的方法。
491 0