WPF的Page介紹及Page Window Frame 之間的鏈接使用示例,嵌套問題


本文源參考 http://www.cnblogs.com/ListenFly/archive/2013/02/24/2923474.html 謝謝源作者

WPF中的Page相比Window來說更加的精簡,因為他沒有提供一個Show或者是Hide的方法,而是通過鏈接的方式進行頁面切換。此外, 一般來說Page不設置自身的大小,因為頁面的尺寸由包含它的宿主窗體來決定的。如果設置了頁面的Width和Height大小,如果宿主的大小小於頁面 的,則頁面會被裁剪;如果宿主的大小大於頁面的,則頁面會居中顯示。同時頁面可以設置WindowWidth和WindowHeight以及 WindowTitle來設置宿主的寬度、高度、標題屬性。

  先看個例子:

            NavigationWindow win = new NavigationWindow();
            //未設置大小
            //win.Content = new Page1();
            //宿主大小大於Page尺寸
            //win.Content = new Page1(300,300,500,500);
            //宿主大小小於Page尺寸
            win.Content = new Page1(500, 500, 300, 300);
            win.Show();

  例子中設置了三種不同情況下頁面和宿主窗體之間的大小關系,看到的三種情況如下

  

 

  

 

  

 

  三張圖片分別為,未對窗體進行大小設置,宿主大於頁面,宿主小於頁面.

  下面介紹下Page頁面的宿主問題:

Page的宿主包括瀏覽器,導航窗口(NavigationWindow)和Frame,上例子中已經使用了NavigationWindow。 后兩種均為WPF提供的Page宿主窗口,提供了從一個Page導航到另一個Page的功能,同時可以記錄歷史導航,以及一系列的導航事件。其中 NavigationWindow繼承自Window,所以在外觀上與普通的窗口最大的區別是多了一個導航工具欄,不過可以通過設置 ShowsNavigationUI屬性控制是否顯示。

  NavigationWindow為頂級窗口,不允許嵌入到其他的元素中。而 Frame則為輕量級,可以嵌入到其他元素中,如NavigationWindow或者Page,甚至Frame的嵌套。Frame默認沒有導航欄,可以 設置NavigationUIVisibility屬性為Visible使其顯示。

  例子,如下例子在NavigationWindow中放置了一個Page,然后在Page中嵌套了一個Frame:

<Page x:Class="WpfApplication4.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="300"
    Title="Page1">
    <Border BorderBrush="Red" BorderThickness="2" Margin="2">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Text="該頁面的宿主窗口是一個NavigationWindow"
                        HorizontalAlignment="Center" VerticalAlignment="Center"  ></TextBlock>
            <Frame Source="Page2.xaml" NavigationUIVisibility="Visible" Grid.Row="1"></Frame>
        </Grid>
    </Border>
</Page>

  同時設置App中的StartUrl為Page,效果如下:

  

 

  可以看到,最外層是擁有導航的NavigationWindow,而內層還嵌套一個擁有導航的Frame.

  細心的童鞋會發現,在上例子中我們並沒有添加NavigationWindow的代碼,可為什么還是有了效果呢?這是因為當設置了StartUri的對象為Page而不是Window,WPF就會為該Page創建一個NavigationWindow。

  下面開始介紹Page之間的導航鏈接:

  1.超鏈接(HyperLink)

 <Hyperlink Click="Hyperlink_Click_1">開始閱讀路由事件</Hyperlink> <Hyperlink NavigateUri="Page4.xaml">開始閱讀路由事件</Hyperlink>
  private void Hyperlink_Click_1(object sender, RoutedEventArgs e) { NavigationService.Navigate(new Uri("pack://application:,,,/Page4.xaml")); }

 

  上述代碼使用了HyperLink的兩種方式進行導航,一種是設置NavigateUri屬性為目標頁,另一種是使用NavigationService類的Navigate方法來進行導航頁(當然,此方法不限於

  HyperLink使用).

  除了上述比較簡單的使用外,HyperLink還可以在元素之間進行導航,例子如下:

復制代碼
<Page x:Class="WpfApplication4.Page4" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Title="Page4"> <Grid> <FlowDocumentReader> <FlowDocument> <Paragraph x:Name="para" FontSize="24" Background="AliceBlue"> <Figure Width="100" Height="100" HorizontalAnchor="ColumnRight" HorizontalOffset="-10" VerticalAnchor="ParagraphTop" VerticalOffset="-30"> <BlockUIContainer> <Image Source="bee.png"/> </BlockUIContainer> </Figure> 路由事件(Routed Event) </Paragraph> <Section FontFamily="華文仿宋"> <Paragraph> 黃蓉凝目看去,只見那兩只玉蜂雙翅上也都有字,那六個字也是一模一樣,右翅是“情谷底”,左翅是“我在絕”。黃蓉大奇,暗想:“造物雖奇,也決造不出這樣一批蜜蜂來之理。其中必有緣故。” …… </Paragraph> <Paragraph> 黃蓉不答,只是輕輕念着:“情谷底,我在絕。情谷底,我在絕。”她念了幾遍,隨即省悟:“啊!那是‘我在絕情谷底’。是誰在絕情谷底啊?難道是襄兒?”心中怦怦亂跳…… </Paragraph> <Paragraph TextAlignment="Right"> ——《神雕俠侶:第三十八回 生死茫茫》 </Paragraph> </Section> <Section LineHeight="25" FontSize="15"> <Paragraph > 這一段講的是小龍女深陷絕情谷地,用花樹上的細刺,在玉蜂翅上刺下‘我在絕情谷底’六字,盼望玉蜂飛上之后,能為人發現。結果蜂翅上的細字被周伯通發現,而給黃蓉隱約猜到了其中含義。本節內容包括: </Paragraph> <List > <ListItem> <Paragraph> <Hyperlink NavigateUri="Page4.xaml#first"> <!--<Hyperlink Click="Hyperlink_Click">--> 從玉蜂說起,回顧.Net事件模型 </Hyperlink> </Paragraph> </ListItem> <ListItem> <Paragraph> <Hyperlink NavigateUri="Page4.xaml#second"> 什么是路由事件? </Hyperlink> </Paragraph> </ListItem> <ListItem> <Paragraph> CLR事件足夠完美,為什么還需要路由事件? </Paragraph> </ListItem> <ListItem> <Paragraph> 言歸正傳,話路由事件 </Paragraph> </ListItem> <ListItem> <Paragraph> 路由事件的實例 </Paragraph> </ListItem> </List> </Section> <Paragraph x:Name="first" FontSize="20" Background="AliceBlue"> 1. 從玉蜂說起,回顧.Net事件模型 </Paragraph> <Paragraph> 木木熟悉神雕俠侶的故事,於是他根據“玉蜂傳信”這樣一個故事,信手畫下這樣一幅有趣的圖。 </Paragraph> <BlockUIContainer> <Image Source="routedevent.jpg"/> </BlockUIContainer> <Paragraph> 其實這一幅“玉蜂傳信圖”暗合.Net的事件模型。小龍女是事件的發布者,她發布了事件“我在絕情谷底”;老頑童和黃蓉是事件的訂閱者,不過老頑童並沒有處理該事件,而黃蓉處理了事件,隱約能猜出其中含義;至於可憐的小楊過,則根本沒有訂閱事件,只是苦苦念叨“龍兒,龍兒,你在哪兒……”;而玉蜂正是傳遞信息的事件。事件,事件的發布者和事件的訂閱者構成了.Net事件模型的三個角色。在.Net當中,一個事件是用關鍵字event來表示的。如下代碼所示: </Paragraph> <Paragraph xml:space="preserve" Background="#88888888"> public delegate void WhiteBee(string param); //聲明了玉蜂的委托 // 小龍女類 class XiaoLongnv { public event WhiteBee WhiteBeeEvent; //玉蜂事件 public void OnFlyBee() { Console.WriteLine("小龍女在谷底日復一日地放着玉蜂,希望楊過有一天能看到....."); WhiteBeeEvent(msg); } private string msg = "我在絕情谷底"; } // 老頑童類 class LaoWantong { public void ProcessBeeLetter(string msg) { Console.WriteLine("老頑童:小蜜蜂、小蜜蜂,別跑"); } } // 黃蓉類 class Huangrong { public void ProcessBeeLetter(string msg) { Console.WriteLine("黃蓉:\"{0}\",莫非......",msg); } } // 楊過類 class YangGuo { public void ProcessBeeLetter(string msg) { Console.WriteLine("楊過:\"{0}\",我一定會找她!", msg); } public void Sign() { Console.WriteLine("楊過嘆息:龍兒,你在哪兒...."); } } static void Main(string[] args) { // 第一步 人物介紹 XiaoLongnv longnv = new XiaoLongnv(); //小龍女 LaoWantong wantong = new LaoWantong(); //老頑童 Huangrong rong = new Huangrong(); //黃蓉 YangGuo guo = new YangGuo(); //楊過 // 第二步 訂閱事件,唯獨沒有訂閱楊過的ProcessBeeLetter; longnv.WhiteBeeEvent += wantong.ProcessBeeLetter; longnv.WhiteBeeEvent += rong.ProcessBeeLetter; // longnv.WhiteBeeEvent += guo.ProcessBeeLetter; //楊過是沒有訂閱小龍女的玉蜂事件 // 第三步 小龍女玉蜂傳信 longnv.OnFlyBee(); // 第四步 楊過嘆息 guo.Sign(); } </Paragraph> <Paragraph x:Name="second" FontSize="20" Background="AliceBlue"> 2. 什么是路由事件? </Paragraph> <Paragraph> 什么是路由事件呢?木木很快查看了一下MSDN,MSDN從功能和實現兩種視角給出了路由事件的定義。 </Paragraph> <Paragraph> Functional definition: A routed event is a type of event that can invoke handlers on multiple listeners in an element tree, rather than just on the object that raised the event. </Paragraph> <Paragraph> Implementation definition: A routed event is a CLR event that is backed by an instance of the RoutedEvent class and is processed by the Windows Presentation Foundation (WPF) event system. </Paragraph> <Paragraph> 雖然木木現在英語功底已經進步了很多,但是這兩個定義還是讓他看得一頭霧水。看來必須得找個例子有點感性的認識(以大家都非常熟悉的Button的Click事件為例,該事件是個路由事件,可以通過Reflector查看ButtonBase的源碼)。 </Paragraph> </FlowDocument> </FlowDocumentReader> </Grid> </Page>
復制代碼
                        </ListItem> <ListItem> <Paragraph> 路由事件的實例 </Paragraph> </ListItem> </List> </Section> <Paragraph x:Name="first" FontSize="20" Background="AliceBlue"> 1. 從玉蜂說起,回顧.Net事件模型 </Paragraph> <Paragraph> 木木熟悉神雕俠侶的故事,於是他根據“玉蜂傳信”這樣一個故事,信手畫下這樣一幅有趣的圖。 </Paragraph> <BlockUIContainer> <Image Source="routedevent.jpg"/> </BlockUIContainer> <Paragraph> 其實這一幅“玉蜂傳信圖”暗合.Net的事件模型。小龍女是事件的發布者,她發布了事件“我在絕情谷底”;老頑童和黃蓉是事件的訂閱者,不過老頑童並沒有處理該事件,而黃蓉處理了事件,隱約能猜出其中含義;至於可憐的小楊過,則根本沒有訂閱事件,只是苦苦念叨“龍兒,龍兒,你在哪兒……”;而玉蜂正是傳遞信息的事件。事件,事件的發布者和事件的訂閱者構成了.Net事件模型的三個角色。在.Net當中,一個事件是用關鍵字event來表示的。如下代碼所示: </Paragraph> <Paragraph xml:space="preserve" Background="#88888888"> public delegate void WhiteBee(string param); //聲明了玉蜂的委托 // 小龍女類 class XiaoLongnv { public event WhiteBee WhiteBeeEvent; //玉蜂事件 public void OnFlyBee() { Console.WriteLine("小龍女在谷底日復一日地放着玉蜂,希望楊過有一天能看到....."); WhiteBeeEvent(msg); } private string msg = "我在絕情谷底"; } // 老頑童類 class LaoWantong { public void ProcessBeeLetter(string msg) { Console.WriteLine("老頑童:小蜜蜂、小蜜蜂,別跑"); } } // 黃蓉類 class Huangrong { public void ProcessBeeLetter(string msg) { Console.WriteLine("黃蓉:\"{0}\",莫非......",msg); } } // 楊過類 class YangGuo { public void ProcessBeeLetter(string msg) { Console.WriteLine("楊過:\"{0}\",我一定會找她!", msg); } public void Sign() { Console.WriteLine("楊過嘆息:龍兒,你在哪兒...."); } } static void Main(string[] args) { // 第一步 人物介紹 XiaoLongnv longnv = new XiaoLongnv(); //小龍女 LaoWantong wantong = new LaoWantong(); //老頑童 Huangrong rong = new Huangrong(); //黃蓉 YangGuo guo = new YangGuo(); //楊過 // 第二步 訂閱事件,唯獨沒有訂閱楊過的ProcessBeeLetter; longnv.WhiteBeeEvent += wantong.ProcessBeeLetter; longnv.WhiteBeeEvent += rong.ProcessBeeLetter; // longnv.WhiteBeeEvent += guo.ProcessBeeLetter; //楊過是沒有訂閱小龍女的玉蜂事件 // 第三步 小龍女玉蜂傳信 longnv.OnFlyBee(); // 第四步 楊過嘆息 guo.Sign(); } </Paragraph> <Paragraph x:Name="second" FontSize="20" Background="AliceBlue"> 2. 什么是路由事件? </Paragraph> <Paragraph> 什么是路由事件呢?木木很快查看了一下MSDN,MSDN從功能和實現兩種視角給出了路由事件的定義。 </Paragraph> <Paragraph> Functional definition: A routed event is a type of event that can invoke handlers on multiple listeners in an element tree, rather than just on the object that raised the event. </Paragraph> <Paragraph> Implementation definition: A routed event is a CLR event that is backed by an instance of the RoutedEvent class and is processed by the Windows Presentation Foundation (WPF) event system. </Paragraph> <Paragraph> 雖然木木現在英語功底已經進步了很多,但是這兩個定義還是讓他看得一頭霧水。看來必須得找個例子有點感性的認識(以大家都非常熟悉的Button的Click事件為例,該事件是個路由事件,可以通過Reflector查看ButtonBase的源碼)。 </Paragraph> </FlowDocument> </FlowDocumentReader> </Grid> </Page>

上述代碼較長(摘抄自 WPF葵花寶典),使用了一個FlowDocumentReader文本閱讀控件,在其中有多個段落(Paragraph),同時在HyperLink中設置了NavigateUri,可以看到
屬性值除了包含xaml名稱之外,還包含了"#"這樣的符號,沒錯這個就是類似於Html中的,本頁之間的超鏈,通過指定"#元素名稱",在點擊HyperLink之后,就可以導航到Name
為所指定的元素。

 導航工具欄:

上圖中的功能是不是很方便呢,這個在WPF中也很容易的實現.
首先,同樣的設置一個Page為起始頁(WPF會自動添加一個NavigationWindow),然后放置一個按鈕按鈕用於跳轉,點擊之后你會神奇的發現,點擊導航欄的下拉會顯示之前訪問的頁面和當前頁面的鏈接.
不知道細心的童鞋會思考一個問題,這個鏈接的文本是怎么得到的呢,問題問的好,這個鏈接的文本可以來自多個屬性,但是最終卻是有一個會被使用,優先級如下:
JournalEntry.Name(在Page中設置,一個附加屬性)>Page.Title>Page.WindowTitle。
當然,點擊工具欄的前進和后退,也可以導航到之前訪問的頁面去。除了導航欄可以實現前進后退,在其他的按鈕中也是可以的,代碼如下:

            <Button Content="后退" Command="NavigationCommands.BrowseBack"></Button> <Button Content="前進" Command="NavigationCommands.BrowseForward"></Button>

只需指定按鈕的Command屬性為對應的命令即可,是不是很簡單呢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM