開發 Windows Phone 7 應用程式時,我們經常需要彈出一個對話方塊(Popup Dialog)來向使用者提示一些資訊,或向使用者索取輸入資訊。相比於完全導航(Navigate)到一個新的介面,半遮掩式的快顯視窗顯得更加輕便(Lightweight),也提供更加緊湊的互動上下文環境(Interaction Context)。這一點尤其適用於那些些內容相對簡單、控制項數量相對較少的介面。然而,Windows Phone 7 SDK 中,並沒有對彈出對話方塊提供太多的功能。最常用的也就是 MessageBox.Show() 而已。
在這片文章裡,我將介紹如何構建一個可重用的彈出框容器(PopupContainer)。首先來看一下運行效果:
下載範例程式碼
一些說明:
- 彈出框中的內容地區完全由開發人員自訂,彈出框的高度自動適應。
- 顯示時由上至下滑落,關閉時由下至上回升。
- 關閉彈出框的方式有三種:
1. 點擊彈出框中的 OK 或 Cancel 按鈕。
2. 點擊彈出框下灰濛濛的的遮罩(mask)地區。
3. 按下 Windows Phone 7 的物理回退按鈕(Back Key)。
- 彈出框底部帶有陰影製作效果,增加立體層次感。
使用方法:
既然是可重用的功能,當然希望它的用法越簡單越好。因此,我將彈出框的功能封裝為一個容器,並接受任意一個使用者控制項(UserControl)做為其顯示內容,並負責用彈出框的形式來顯示和隱藏。在某個頁面(例如:自動產生的 MainPage)的一個按鈕點擊事件中,只需要寫下如下代碼:
PopupCotainer pc = new PopupCotainer(this);
pc.Show(new UserControl1());
上述代碼中:
1. PopupContainer 就是本文所討論的可重用的彈出框容器類。
2. 建立一個 PopupContainer 對象時,需要傳遞當前的頁面對象(this),其目的是讓它能夠監聽並響應 BackKeyPress 事件,關閉彈出框。
3. 調用 PopupContainer 對象的 Show() 方法,並傳遞一個使用者控制項,用彈出框的形式進行顯示。UserControl1是一個使用者控制項(當然也可以是一個PhoneApplicationPage)。
為了給開發人員提供儘可能大的自由度,PopupContainer 本身並不提供任何內建的 OK 或 Cancel 之類的按鈕,而是把這部分工作留給開發人員自己去完成。那麼,以上述代碼為例,我們就需要在 UserControl1 中設定一兩個按鈕,並在其點擊事件(Click Event)中,寫下如下代碼,以關閉彈出框:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.CloseMeAsPopup();
}
咦?CloseMeAsPopup() 方法是哪裡來的呢? 預設的 UserControl 類中並不包含這樣的方法啊?
沒錯!這個方法其實是 PopupContainer 提供的一個擴充方法(Extension Method)。有了這樣的擴充方法,在一個使用者控制項中,關閉包含它的彈出框就只需要一行代碼而已!
怎麼樣,夠簡單吧?
如果你對如何?這樣一個 PopupContainer 感興趣,並希望在此基礎上進行擴充和改進,請繼續閱讀下面的具體說明。
原理解析:
1. PopupContainer 是一個使用者自訂控制項。查看 PopupCotainer.xaml 檔案內容,裡面主要定義了三個元素:
- contentArea:用於承載和顯示彈出框裡的具體內容。
- mask:介於彈出框內容及底層頁面之間的遮罩層。
- shadow:定義一個漸層色填充的矩形,作為彈出框的陰影地區。
2. PopupContainer 實際上是藉助 Windows Phone 7 SDK 內建的 Popup 類來實現彈出框的功能。在執行個體代碼項目中,查看 PopupCotainer.xaml.cs 檔案中的 Show() 方法。Show() 方法建立 Popup 對象,並設定其 IsOpen 屬性為 true。這一賦值過程會觸發 PopupContainer 控制項的 Loaded 事件(對應 PopupCotainer_Loaded() 方法)。在 PopupCotainer_Loaded() 方法中進行彈出框的顯示。
3. 彈出框顯示時由上至下滑落的效果,使用一段故事版動畫(Storyboard Animation)。查看 PopupCotainer.xaml.cs 檔案中的 PrepareShowStory() 方法。在該方法的入口處,將傳遞給它的內容控制項植入到 contentArea 中,並調用 UpdateLayout() 方法,強制更新 UI,從而獲得內容地區的真實高度,繼而決定彈出框下落的幅度。
4. 關閉彈出框時彈回的效果,同樣使用一段故事版動畫(Storyboard Animation)。查看 PopupCotainer.xaml.cs 檔案中的 PrepareCloseStory() 方法。不僅如此,在彈出框滑落過程中,使用者點擊遮罩層(mask)或後退按鈕時,為了讓彈出框的退回效果連貫,在該方法中,動態地設定了動畫的起始值(查看 animation.From)。
5. PopupContainer 還註冊監聽觸發頁面的 BackKeyPress 事件,以實現在使用者點擊物理回退按鈕時,關閉自身。
6. 在 PopupCotainer.xaml.cs 檔案中還定義了一個 PopupManager 類,裡面定義了一個擴充方法 CloseMeAsPopup(),用來提供在彈出框內容控制項內部,關閉包含它的彈出框。(其調用樣本可以查看 UserControl1.xaml.cs 檔案中的 OKButton_Click() 方法或 CancelButton_Click() 方法)
OK,PopupContainer 的實現邏輯就介紹到這裡,更具體的內容可以查看範例程式碼。
希望對各位朋友的工作有所協助。