Windows Presentation Foundation資源

iDotNetSpace發表於2008-01-22
到目前為止,我們討論了嵌入應用程式部件的頁面。但是,內容可以從很多地方載入--它可能被嵌入了程式碼所使用的部件、可能被嵌入一個被引用的部件、或者由一組鬆散的內容檔案組成,根本沒有嵌入任何部件。鬆散的內容本身可以位於本地磁碟、檔案共享、甚至於Web站點上。並且,無論內容是嵌入的還是鬆散的,它都不一定是頁面;內容可能包括多種媒體,例如影像、視訊和音訊。最後,內容也不一定屬於某個特定的應用程式。屬於其它Web應用程式的HTML頁面也是可行的。

  這種靈活性允許開發者更簡單地處理大量的現實問題。有時候內容對於應用程式來說足夠特別,而且該應用程式是如此依賴這個內容,以至於需要把內容嵌入部件中來部署內容和應用程式。有些應用程式的內容經常變換,以至於重新構建部件和重新部署新內容變得不切實際,因而支援鬆散的內容(由於鬆散的內容可以位於通常的位置,基於Internet和內部網的XBAP應用程式可以避免下載不必要的部件)。此外,有些內容在多個應用程式之間共享,但是仍然需要保證它們可供使用。

  為了保證靈活性,Windows Presentation Foundation為了唯一標識和載入資源,使用了一種特殊的機制。它不考慮內容的位置或內容是嵌入還是鬆散的。這種機制的基礎是Pack URI大綱(scheme),它是一種用不同的URI標識應用程式資源的可擴充套件大綱。Windows Presentation Foundation利用Pack URI大綱來支援幾種用於載入內容的不同的、但是常見的情形。

  在整篇文章中,無論什麼時候使用Application.StartupUri 和Hyperlink.NavigateUri,示例程式碼都使用Pack URI來標識和載入窗體和頁面:

<!--App.xaml (markup)-->
<Application ... StartupUri="HomePage.xaml" />

  這個例子使用了Pack URI的相對版本,它是一種很好的簡化操作,允許你輸入更少的內容。Pack URI的完整版本如下所示:

pack://application:,,,/HomePage.xaml

  完整的Pack URI由三個關鍵的部分組成:大綱(pack://)、擁有者(application:)和路徑(,/HomePage.xaml)。其中擁有者描述了擁有資源的容器的型別,而路徑描述了資源與容器的相對位置。"application:"容器是一個真正的部件,而路徑是資源相對部件的根(root)的位置。

  不管使用完整的或相對的Pack URI,它所指向的內容即可以嵌入部件的內部,也可以是儲存在與應用程式執行檔案相關的某個位置的鬆散的XMAL檔案。對於一個存放在應用程式可執行檔案目錄中的鬆散XAML頁面來說,其Pack URI如下所示:

pack://application:,,,/HomePage.xaml

  有趣的是,這個鬆散的XAML檔案的Pack URI與嵌入部件的Pack URI相同。為了區分兩者,Windows Presentation Foundation使用了一個基本的解析機制,在查詢鬆散資源之間,它首先在部件中查詢嵌入的資源。

  Pack URI還用於訪問那些嵌入被引用的部件中的Windows Presentation Foundation資源,只是有細微的語法差別:

pack://application:,,,/BoxApplicationLibrary;component/HomePage.xaml

  相對的Pack URI等同於:

/BoxApplicationLibrary;component/HomePage.xaml

  Pack URI允許你從應用程式的原始站點(載入應用程式的位置)來定位和載入資源。對於Web伺服器上載入的XBAP應用程式來說,讓內容保持在當前位置同把新內容放入應用程式的釋出位置一樣簡單。為了訪問原始站點的鬆散資源,你必須使用另外一個特定型別的Pack URI,它只能使用完整路徑:

pack://siteoforigin:,,,/HomePage.xaml

  你可以導航到頁面(無論是嵌入的還是鬆散的)的任何一個片段(fragment)。這與Web樣式的片段導航是類似的。通過指定Name屬性,你就可以在頁面上定義片段了,如下所示:

<Page ... >
<TextBlock Name="Paragraph1" TextWrapping="Wrap">
...
</TextBlock>
</Page>

  為了導航到頁面片段,你需要使用另外一種特殊的Pack URI,在頁面URI上附加"#XAMLElementName",如下所示:

HelpPage3.xaml#Paragraph3

  頁面函式(PageFunction)

  由於內容來自於多個位置,而超連結驅動的應用程式又允許使用者導航到任何位置,從而使完成一項事務變得非常困難。這是因為超連結驅動的應用程式不能輕易地約束使用者導航到特定頁面。無論應用程式提供了多少個超連結,使用者仍然可以使用瀏覽器的位址列導航到任何地方。其結果是,使用者可以離開發起事務的頁面,而不考慮事務是否完成了。在Web世界中,有很多技巧可用於建立類似對話方塊樣式行為、依賴對話狀態等的Web頁面。不幸的是,這需要大量的開銷。對話方塊的確可以解決這個問題,但是由於安全性原因,Window不能從應用程式中例項化,例如XBAP的對話方塊就只能在Internet區域部分信任環境中執行。

  幸運的是,Windows Presentation Foundation通過頁面函式支援模式對話方塊樣式的機制。它們被封裝為泛化的PageFunction型別,直接衍生自Page。因而PageFunction的樣子與頁面類似,它的建立方式也相似,如下段所示。

  程式碼:PageFunction

<!--OrderABoxPageFunction.xaml (markup) -->
<PageFunction
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BoxApplicationXBAP"
x:Class="BoxApplicationXBAP.OrderABoxPageFunction"
x:TypeArguments="local:Order"
WindowTitle="Box Application - Order a Box" >
...
<!--Content-->
...
<PageFunction>

// OrderABoxPageFunction.cs (code-behind)
public partial class OrderABoxPageFunction:
PageFunction<Order> { ... }

  這個特定的頁面函式的目標是收集新訂單的資訊,它被Order封裝了。由於典型情況下事務都是這樣運算元據的,PageFunction是一個泛型(generic),並被宣告用於操作特定的資料(標記中特定的x:TypeArguments屬性)。如果x:TypeArguments的值和泛化的PageFunction型別的引數不匹配,就會出現編譯錯誤。

  呼叫PageFunction的頁面需要例項化PageFunction並手動導航到該頁面上:

// HomePage.cs (codebehind)
public partial class HomePage : Page
{
 void orderHyperlink_Click(object sender, RoutedEventArgs e)
 {
  OrderABoxPageFunction pageFunction = new OrderABoxPageFunction();
  pageFunction.Return += new ReturnEventHandler<Order>(OrderABoxPageFunction_Returned);
  this.NavigationService.Navigate(pageFunction);
 }
 ...
}

  接下來,PageFunction在給呼叫頁面返回結果之前,必須允許使用者完成頁面:

// OrderABoxPageFunction.cs (codebehind)
public partial class OrderABoxPageFunction:
PageFunction<Order>
{
void orderHyperlink_Click(object sender, RoutedEventArgs e)
{
// 返回訂單
this.OnReturn(new ReturnEventArgs<Order>(this.order));
}
void cancelHyperlink_Click(object sender, RoutedEventArgs e)
{
// 取消訂單
this.OnReturn(null);
}
...
}

  接下來呼叫PageFunction.OnReturn返回,傳遞一個泛化的ReturnEventArgs例項。如果事務被接受了,它就包含一個PageFunction所操作的型別例項。否則,它就是空的。為了檢測PageFunction的返回,並獲取ReturnEventArgs和其資料,呼叫頁面需要處理PageFunction.Returned事件,如下段程式碼所示。被返回的資料存放在Returned事件處理程式的ReturnEventArgs引數的Result屬性中。

  程式碼:PageFunction.Returned

// HomePage.cs (code-behind)
public partial class HomePage : Page
{
 // 載入頁面函式
 void orderHyperlink_Click(object sender, RoutedEventArgs e)
 {
  OrderABoxPageFunction pageFunction = new OrderABoxPageFunction();
  pageFunction.Return += new ReturnEventHandler<Order>(OrderABoxPageFunction_Returned);
  this.NavigationService.Navigate(pageFunction);
 }
 // 處理頁面函式的返回
 void OrderABoxPageFunction_Returned(object sender, ReturnEventArgs<Order> e)
 {
  if (e != null) this.orders.Add(e.Result);
 } 
 ...
}

  你可能希望在事務完成之後,確保PageFunction從導航歷史中移除。這隻需要一個簡單的配置:

<!--OrderABoxPageFunction.xaml (markup) -->
<PageFunction RemoveFromJournal="True" ... >
...
<!--Content-->
...
<PageFunction>

  通過從導航歷史中刪除頁面函式,你可以阻止使用者導航回該頁面函式。這是非常重要的,因為如果不這樣處理,使用者就可能修改那些已經發生改變的資料,從而造成潛在的資料不一致風險。

  我們的位置

  Windows Presentation Foundation應用程式模型是非常靈活的。它支援標準的和瀏覽器寄宿的應用程式--它們兩者都支援選單驅動和超連結驅動的導航。此外,應用程式的內容可以被封裝到應用程式的部件、被引用的部件或某些位置的鬆散檔案中。總而言之,在Windows Presentation Foundation應用程式模型中建立的使用者體驗型別僅受個人選擇的限制。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-157080/,如需轉載,請註明出處,否則將追究法律責任。

相關文章