天天看點

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

樣式如下:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

這個例子可以拿來直接用。處理這種布局,主要是需要處理在PC/Mobile不同螢幕寬度下的具體顯示内容,可以使用VisualState來實作不同狀态的切換。

為了将WP8.1版本的項目快速更新到UWP版本,我沒有使用官方示例的方式,而是在MainPage裡放了兩個Frame,在左側的Frame裡放一個清單Page,右側Frame裡放一個詳情Page,這樣之前的頁面的UI和ViewModel都可以原封不動的拿過來,隻需要單獨處理VisualState的切換就可以了。

下面以一個簡單的例子來說一下是如何實作的。最近關于Win10 UWP的内容寫了不少,都是在開發的過程中,把能單獨拿出來的部分再重新做一遍demo,是以如果大家有興趣的話可以照着動手敲一遍,自己實作出來才會了解的更深入。

首先建立一個MVVM-Sidekick項目,命名為MasterDetailDemo。

添加Models目錄,建立一個NewsItem:

建立一個ItemsDataSource類,用于模拟資料,可以傳回一些資料。具體代碼看Demo裡的。

在MainPage中放置一個Grid控件,分為兩列,左側和右側分别放兩個Frame控件:

然後添加兩個頁面,MasterPage和DetailPage。

MasterPage中放置一個ListView控件,調用剛才的ItemsDataSource類,把資料綁定到ListView上,這個就不用詳述了吧。還要給ListView設定項模闆。這部分代碼就不貼了。

現在讓MainPage頁面載入時,左側的Frame自動顯示MasterPage。

打開MainPage_Model.cs檔案,取消對OnBindedViewLoad方法的注釋,修改為以下代碼:

好了,現在當MainPage頁面加載完成後,名為masterFrame的Frame會顯示MasterPage的内容,像下面這樣:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

然後要實作點選項的時候,要在右側的Frame裡顯示DetailPage。

打開MasterPage.xaml,在頭部引入以下幾個命名空間:

然後修改項模闆,使用SendToEventRouterAction,這個東東在以前的Blog裡說過,在項模闆的Grid裡添加以下代碼:

在MainPage加載的時候,注冊NewsItemTapped事件,來處理點選事件。打開MainPage_Model.cs檔案,在最後添加一個RegisterCommand方法:

别忘了在Loaded事件裡調用這個方法:

因為DetailPage_Model還沒有可接收參數的構造函數,是以需要在DetailPage_Model裡加兩個構造函數,一個是無參的,一個是可接收參數的,同時還需要加一個可綁定的屬性,用來顯示内容:

這樣在DetailPage裡就可以接收到點選的是哪個NewsItem了,再綁定到界面上,我就随便放了個TextBlock:

運作一下看看,怎麼點了沒反應呢,原來在MainPage的Grid裡,第一列就把寬度占滿了,第二列無法顯示了,來給兩個列設定個寬度吧,第一列設定為2*,第二列設定為3*:

現在可以顯示了:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

但是,這隻是第一步,接下來需要處理在不同螢幕寬度下的适配問題,我們可以打開UWP版的郵件,拖動視窗縮放大小,觀察頁面内容變化,可以得出以下特性:

在PC上:

1、當寬度大于一定寬度時,Master和Detail是可以同時顯示的,在剛打開程式沒有點選郵件的時候,右側的Detail實際上顯示了一個空頁面(有背景圖檔);

當逐漸縮小寬度時,又分為兩種情況:

2、如果Detail頁為空頁面時,縮小到一定寬度後,視窗隻顯示Master頁面;

3、如果Detail頁不為空,即顯示郵件正文的時候,縮小到一定寬度後,視窗隻顯示Detail頁面;

在Mobile上:

程式打開時,顯示Master頁面,相當于2;

點選郵件後,顯示Detail頁面,相當于3;

這樣我們可以得出,不管是PC還是Mobile,需要處理三種狀态的切換,我命名為:

NarrowAndBlankDetail

NarrowAndNoBlankDetail

Wide

通過處理這三種狀态的切換,就可以實作類似郵件UWP版的效果了。有些同學可能會問,為什麼不直接使用自帶的AdaptiveTrigger呢,主要是這個AdaptiveTrigger隻能根據寬度來設定,而目前的需求還需要根據Detail頁面是否為空來處理,是以需要自定義一個Trigger了。

郵件UWP預設載入的時候有一個空頁面,是以還需要添加一個BlankPage,這個頁面相當于一個空頁面,裡面可以随便放點什麼東西,比如背景圖檔啊,logo啊,或者廣告什麼的,Trigger會根據Detail頁面是否顯示這個BlankPage來進行處理。

先讓MainPage載入時,預設左側加載MasterPage,右側加載BlankPage:

好,運作效果是這樣:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

現在來處理狀态切換。關于StateTrigger,國外已經有人寫了一個項目,實作了多種Trigger,見:

<a href="https://github.com/dotMorten/WindowsStateTriggers">https://github.com/dotMorten/WindowsStateTriggers</a>

這個項目實作了n個實用的Trigger,但好可惜沒有能滿足我的要求的,還是自己動手吧。我參考了他的代碼,繼承了他的接口ITriggerValue,繼承此接口的話可以用在CompositeStateTrigger裡,為了友善以後使用按照這個接口來吧。

說一下主要的代碼實作思路。

首先要定義一個枚舉:

頁面寬度的變化,通過訂閱ApplicationView.GetForCurrentView().VisibleBoundsChanged事件來處理,如果寬度大于720時如何,小于720時如何。當然這個720也可以傳遞屬性進來,我懶得弄就寫死在裡面了。

同時,還需要一個DetailContent屬性,這個屬性需要綁定到第二個Frame的Content上,這樣Trigger可以知道目前是不是BlankPage,通過以下代碼來判斷:

全部代碼如下:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果
Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

View Code

我在代碼裡輸出了一些資訊,調試的時候可以觀察各種狀态是在什麼時候切換的。

然後在MainPage.xaml裡 應用這個StateTrigger,首先,要在MainPage的ViewModel裡添加一個object,用于綁定DetailFrame的内容:

MainPage.xaml裡的第二個Frame的Content綁定到這個DetailContent上:

注意Mode要設定為TwoWay,這樣才可以讓Trigger知道DetaiFrame的内容。在MainPage.xaml的根Grid裡添加以下Trigger:

還要把預設的gridMain的兩列的寬度預設值分别改為*和0:

Trigger的意義很清楚了,Setter會根據不同的狀态去設定gridMain兩列的寬度來控制MasterPage和DetailPage的顯示和隐藏:

當剛開始進入程式,左側顯示清單,右側顯示BlankPage,這時候如果寬度大于720,兩個頁面正常展示,如果頁面寬度小于720,則隻顯示清單頁;

如果頁面寬度大于720的時候,點選清單,右側正常顯示詳情;

如果頁面寬度小于720,點選清單,清單會隐藏,隻顯示詳情;

基本達到了文章開頭提出的目的。

當在手機上運作的時候,就會發現當點選清單顯示DetailPage後,再按傳回鍵直接退出程式了。因為還沒有處理傳回鍵事件。PC上也一樣,程式左上角應該有個傳回按鈕。下面來處理傳回事件。

基本思路是,點選傳回後,應該先判斷DetailPage是否可GoBack,如果可以就GoBack,直到傳回最開始的BlankPage為止,這樣StateTrigger會自動觸發NarrowAndBlankDetail狀态,顯示MasterPage。

傳回是處理SystemNavigationManager.GetForCurrentView().BackRequested這個事件,打開MainPage.xaml.cs檔案,在OnNavigatedTo裡訂閱這個事件:

使用者點選傳回鍵的時候,首先看DetailPage能否GoBack,再看MasterPage能否GoBack,當沒有可GoBack的時候就把傳回鍵隐藏。

在PC上的傳回鍵預設是隐藏的,還需要在導航到詳情頁的時候将其展示出來,修改MainPage_Model.cs檔案裡的RegisterCommand方法:

現在運作一下,PC上也可以傳回了。當第一次打開的時候,是這樣 的:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

如果拖動視窗縮小,則隻會顯示MasterPage:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

當點選清單項時,會隻顯示DetailPage:

Win10 UWP開發系列:實作Master/Detail布局一、建立項目及Model二、頁面布局三、自定義StateTrigger四、處理傳回鍵五、添加切換動畫效果

點選左上角傳回鍵,又隻顯示MasterPage了。

具體切換動畫我不會截圖,大家可以下載下傳demo自己試試。

我們還可以做的更美觀一點。UWP預設的Page切換是有動畫效果的,但這裡因為隻使用StateTrigger設定了Grid的列寬,當從DetailPage傳回MasterPage的時候MasterPage一下子就顯示出來了,感覺有點生硬。現在給切換加一個動畫。

在NarrowAndBlankDetail的VisualState裡,添加一段StoryBoard:

設定透明度從0到1,同時有一個移動的效果。注意這裡的StoryBoard.TargetProperty的寫法,詳細說明可以參考MSDN文檔:

<a href="https://msdn.microsoft.com/zh-cn/library/windows/apps/windows.ui.xaml.media.animation.storyboard.targetproperty.aspx">https://msdn.microsoft.com/zh-cn/library/windows/apps/windows.ui.xaml.media.animation.storyboard.targetproperty.aspx</a>

<a href="https://msdn.microsoft.com/zh-cn/library/windows/apps/jj569302.aspx">https://msdn.microsoft.com/zh-cn/library/windows/apps/jj569302.aspx</a>

再次吐槽一下MSDN文檔真是太難找了。版本太多。

在&lt;VisualStateManager.VisualStateGroups&gt;裡添加Transitions:

同時要在gridMain裡添加以下代碼:

不然動畫無法起作用。

現在運作一下看看,傳回的時候MasterPage也是從左側漸變滑入的,效果好了不少。

這種方式基本可以把WP8.1的代碼直接拿過來用,頁面改動不大。如果您有更好的實作方式,歡迎留言讨論。

這篇基本就寫到這裡了。最近WP圈一片哀嚎,很多無奈的事情。但作為普通個人開發者來說,抱怨也沒用,能做多少就做多少吧,總好過隻吐槽。行動的意義永遠大于口頭空講。

本文得到了禮物說開發者鄭大神的鼎力支援。希望大家下載下傳他的禮物說,做的非常漂亮。

預祝大家新春快樂!

最後給出demo下載下傳:連結:http://pan.baidu.com/s/1hqQTbEW 密碼:ilar

繼續閱讀