zoukankan      html  css  js  c++  java
  • SIlverlight中的导航总结

    导航经常在程序中要用到,Silverlight中的导航分为两大类,三小类.

     两大类:使用导航框架来完成(Frame,或者NavigationService类(包含在Page类中)),或者使用传统的修改容器的Content或者是Child等内容来实现导航

    下面慢慢来讲解:

    一.通过非框架的方式来完成

      1.其实这种方式的原理很简单,就是修改容器的根元素,比如我们的页面元素如下

        <Grid x:Name="LayoutRoot">

    </Grid>

    没错,就是只有一个Grid,我们可以通过修改Grid的Children来实现导航,代码如下:

                LayoutRoot.Children.Clear();
    LayoutRoot.Children.Add(
    new Page());

    Children是Grid的所有子元素的集合,类型是UIElement,所以我们实例化一个Page(或者是UserControl)来实现导航,切忌,在导航前调用Grid.Children.Clear()方法,这样才能

    保证我们导航到的页面正确.

    2.如果你觉得这种方式太繁琐,ok,我们可以来使用另一种相似的方法来实现,同样是使用Grid,只不过我们这次Grid的位置变了,Grid不在某个页面,而是在App.cs中.没错,我们要定义一个Grid的对象,在App中,如下所示,我们修改App.RootVisual为自定义的Grid,然后通过Grid.Children.Add(Page)来实现页面的跳转,之所以使用这个是,是因为我们可以在任何一个页面访问App的元素,所以我们想修改Grid的Children也非常方便,当我们修改了Grid的Children,页面的RootVisual当然也就修改了.如下:

            public Grid rootGrid = new Grid();
    private void Application_Startup(object sender, StartupEventArgs e)
    {
    UserControl startPage = new UsingContentLoader();
    this.RootVisual = rootGrid;
    rootGrid.Children.Add(startPage);
    }

    在一个页面中通过App.rootGird来跳转页面,如下,在按钮事件中得到当前的App,然后操作rootGrid对象,即可完成跳转:

         private void btnNavigation_Click(object sender, RoutedEventArgs e)
    {
    App app
    = (App)App.Current;
    app.rootGrid.Children.Clear();
    app.rootGrid.Children.Add(
    new MainPage());
    }

    二.通过框架来完成导航

       使用框架的导航我们同样有两个选择,一个是使用Frame来完成导航,而另一个是使用Page的内置类NavigationService来完成,其实本质没有太大区别

      1.使用Frame

       JournalOwnership属性:默认情况下,仅当无法找到包含自己的日记的父导航宿主 (NavigationWindowFrame) 时,Frame 才会使用自己的导航历史记录(例如,如果承载 Frame 的内容由 Window 承载)。 若要强制 Frame 管理自己的导航历史记录,请将 JournalOwnership 设置为 OwnsJournal

       Frame严格来说是一个控件,主要目的就是用来导航,通常和Button和HyperLink结合来使用,写法如下:

       这个是最简单的Frame的写法,仅仅指定了Name(在后台使用Frame的Navigation可以来导航)和Source(默认显示的页面,当然也可以在托管代码来改变,实现导航)

     <sdk:Frame Name="MainFrame" Source="/Navigation/Pages/CustomCachedPage.xaml" />

      通常我们的Frame不止这么简单,还需要指定UriMapping,也就是导航映射,没错,我们指定了导航映射,可以简化我们的导航的代码,下面现在App中定义一个导航资源

      在App.xaml中定义一个UriMapper设定一个Key(这样才知道其他Xaml中指定使用的是哪一个UriMapper),同时注意需要指定一个默认的页面,也就是需要给Source

      一个默认值,所以添加一个Uri为空的映射,这样就实现了默认的映射.当然也可以指定传参的Uri,当我们的Uri满足这样的格式,则会跳转到映射的页面,并传递参数,可以通过

    NavigationContext.QueryString.ContainsKey("id")来判断是否包含某一个参数,使用NavigationContext.QueryString["id"]来得到某一个参数

     <Application.Resources>
    <navigation:UriMapper x:Key="PageMapper">
    <!--必须指定初始页面-->
    <navigation:UriMapping Uri="" MappedUri="/MainPage.xaml"></navigation:UriMapping>
    <navigation:UriMapping Uri="BtnFrame" MappedUri="/Navigation/Frames/BtnFrame.xaml"></navigation:UriMapping>
    <navigation:UriMapping Uri="Products/{id}" MappedUri="/Views/ProductPage.xaml?id={id}"></navigation:UriMapping>
    </navigation:UriMapper>
    </Application.Resources>

    在页面中使用UriMapper,没错,使用StaticResoucr 来使用UriMapper,这样当我们在页面中使用Mainfram.Navigation方法的时候就会使用这个映射规则

    <sdk:Frame Name="MainFrame" UriMapper="{StaticResource PageMapper}" />

    调用导航的方法:

      MainFrame.Navigate(new Uri("BtnFrame", UriKind.Relative));

    使用Frame导航传参:

    指定Mapping:

     <uriMapper:UriMapping Uri="/About/{Id}" MappedUri="/Views/About.xaml?productId={Id}"></uriMapper:UriMapping>

    可以看到除了/About之外加了{Id},这个{Id}表示传递一个参数(当然不一定必须是 Url后边的参数,可以把它当做成一个动态的匹配值,在这里仅仅为参数作用).

    接下来开始使用这个传参的Url:

    <HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}" 
    NavigateUri
    ="/About/test" TargetName="ContentFrame" Content="about"/>

    当然也可以在托管代码中使用,在托管代码中可以使用 Frame的Navigate方法来进行导航.

    ContentFrame.Navigate(new Uri("/About?productId=test",UriKind.RelativeOrAbsolute));

    可以看到Uri是没有xaml后缀的,因为配置了这个Mapping,那么在导航的时候会自己去匹配规则的。

    也可以使用NavigationService(该属性仅仅在Page页面中有,在UserControl是没有的)的Navigate方法。

     this.NavigationService.Navigate(new Uri("/Home?Id=12",UriKind.RelativeOrAbsolute));

    参数是传递过去了,但是接收呢,page类有一个属性NavigationContext(导航上下文对象),该对象有一个属性QueryString,是不是很熟悉,没错作用和ASP.NET中的

    Request.QueryString一样,保存了URl中的参数,但是呢为了保证获得参数的顺利,在使用参数之前对参数进行判断是否存在使用NavigationContext.QueryString.ContainsKey("paramname")或者NavigationContext.QueryString.Keys.Contains("paramname")来判断是否存在,或者参数值则直接通过参数名字获取NavigationContext.QueryString["paramname"].ToString()

       if (this.NavigationContext.QueryString.Keys.Contains("productId"))
    HtmlPage.Window.Alert(this.NavigationContext.QueryString["productId"].ToString());

    2.NavigationService的导航(Page类的导航)

      之所以Page类可以实现导航,那是因为Page类中的NavigationService框架,因为它有好多方法来实现导航的功能.

      下面先来看看Page类有哪些用于导航的东西:

      Page的常用属性:

    属性

    类型

    描述

    NavigationCacheMode

    NavigationCacheMode

    该属性用于获取或设置一个值,改制指定当前导航页面是否开启导航缓存;该属性默认值为Disabled(表示不开启导航缓存),EnabledRequired属性值表示开启导航缓存,其不同的是Required不受CacheSize限制,每次导航时都重复利用缓存实例;而Enabled受制于CacheSize缓存尺寸,超过尺寸时则放弃缓存实例

    NavigationContext

    NavigationContext

    获取当前导航请求中的对象信息,该属性常被用于获取URI查询字符串值,实现导航框架传值

    NavigationService

    NavigationService

    获取当前导航框架导航服务实例,通过该属性可以获取当前页面导航请求,该属性将在后文详细讲解。

    Title

    String

    该属性用于获取或设置当前导航页面的名称

    Page类的方法:

    方法

    描述

    OnFragmentNavigation

    该方法在导航到页面上的片段时被调用

    OnNavigatedFrom

    该方法在当前页面不再为导航框架中的活动页面时被调用

    OnNavigatedTo

    该方法在当前页面成为导航框架中的活动页面时被调用

    OnNavigatingFrom

    该方法在当前页面不再为导航框架中的活动页面前被调用

    刚才提到了Page中很重要的一个属性就是NavigationService,因为他可以作为一个导航框架,那是因为他有很多导航的方法如下:

    方法

    描述

    GoBack

    该方法用于导航当前页面后退到历史记录中上一页,如果后退导航时没有历史记录页面,则返回异常

    GoForward

    该方法用于导航当前页面前进到历史记录中下一页,如果前进导航时没有历史记录页面,则返回异常

    Navigate

    该方法用于导航到指定URI页面,该URI可以是导航映射相对地址,也可以是导航页面绝对地址

    Refresh

    该方法用于重载当前导航页,该方法经常被用于自定义INavigationContentLoader

    StopLoading

    该方法用于停止所有导航异步进程,该方法常被用于停止正在下载载入的导航页面

    NavigationService类提供以下常用属性和事件:

    事件

    描述

    FragmentNavigation

    该事件在导航到内容片段时被激活

    Navigated

    该事件在导航完成时被激活

    Navigating

    该事件在导航开始时被激活

    NavigationFailed

    该事件在导航抛出异常失败时被激活

    NavigationStopped

    该事件在StopLoading方法被调用时,或者取消当前导航请求时被激活

     

    使用NavigationService来导航,其实非常简单,仅仅一行代码实现了页面的跳转:

    this.NavigationService.Navigate(new Uri(“/Home.xaml”, UriKind.Relative));

     对于NavigationService类而言,值得注意的是该类包含两个特殊的方法,分别是Refresh()和StopLoading(), 这两个方法主要针对当前页面进行操作

    Refresh方法,功能类似浏览器的刷新按钮,该方法将重载当前Page类页面,实现页面刷新效果,如果页面允许支持缓存,将从缓存中读取当前页面。
    StopLoading方法,功能类似浏览器的停止按钮,该方法将停止正在运行的页面载入进程或者其他异步进程,在实际项目中,该方法并不常用。

     

    Page类的NavigationContext属性

    该属性包含两个常用的属性,即Uri和QueryString,使用NavigationContext.Uri获取当前URI路径字符串,使用NavigationContext.QueryString来获得页面之间的

    传值,在本文的前边已经有例子.

    string uriText = String.Format(“/User.xaml?userID={0}&role={1}”, userID, userRole);
    mainFrame.Navigate(
    new Uri(uriText), UriKind.Relative);

    使用NavigattionContext.QueryString来获得

    int userID, userRole;
    if (this.NavigationContext.QueryString.ContainsKey(“userID”))
    userID
    = Int32.Parse(this.NavigationContext.QueryString[“userID”]);
    if (this.NavigationContext.QueryString.ContainsKey(“userRole”))
    userRole
    = Int32.Parse(this.NavigationContext.QueryString[“userRole”]);

     Page类的NavigationCacheMode属性

    Page类的NavigationCacheMode属性是Silverlight导航框架重要属性之一,其功能可以保存导航页面状态。 NavigationCacheMode属性中包含有三个枚举成员,分别是Disabled,Required和Enabled,其含义分别是:
     

    NavigationCacheMode.Disabled: 不支持缓存页面,每次导航应用访问时创建 一个新的页面实例;
    NavigationCacheMode.Required: 支持缓存页面,并且每次导航应用访问时都重复利用该缓存实例,而且忽略Frame类中CacheSize属性设置大小;
    NavigationCacheMode.Enabled: 支持缓存页面,如果超过Frame类中CacheSize属性设置尺寸,则放弃保存缓存实例;

     

    默认情况下,NavigationCacheMode为Disabled状态,也就是说,在Silverlight导航框架应用时,不记录任何信息到缓存。当NavigationCacheMode状态设置为Required后,每当用户结束一次导航操作,Frame类将保存页面对象到内存,当用户点击返回或者前进时,将重新载入保存的缓存状态到当前Page类页面,而当前Page类页面的构造函数不再执行,但是其Loaded事件将被激活。当 NavigationCacheMode为Enabled状态时,则会参考Frame类中CacheSize属性设置尺寸设置。例如:如果设置Frame 类CacheSize属性值为6,当第七个Page类页面载入时,第一个载入到缓存的Page类 页面将会从缓存中删除,而最新的Page类页面将会替代。

     

    好了页面导航就先到这吧,希望大家多多指点,本文参考了 冷秋寒大哥的博客,在此表示感谢.

  • 相关阅读:
    二维码生成代码
    部署javaweb项目到阿里云ecs(centos7)
    mysql基础知识
    IDEA快捷键快速补齐类和对象名
    Redis和elasticsearch
    在asp.net 项目的bin目录中使用子目录
    MVC项目引用备注
    OAuth相关备注
    手动安装windows的磁盘清理工具
    在CentOS上安装 MongoDB
  • 原文地址:https://www.cnblogs.com/ListenFly/p/2164525.html
Copyright © 2011-2022 走看看