Windows Phone 7 - 學習使用Popup Control

Windows Phone 7 - 學習使用Popup Control

開發WP7時總是在Silverlight的使用範例與別人的網站中看到使用Popup Control的機會,尤其是像Progress Bar的使用,

通常就會配合PopupControl將Prograss Bar的圖示蓋在目前畫面之上,透過設定Opacity(不透明度)讓畫面可以半透明的

呈現用戶得知目前正在執行一些任務。或是Popup出特定的User Control,協助用戶操作與完成任務。

 

這樣的操作效果,在WP7其實也蠻常用的,一來可以省掉NavigationService移動畫面要重新走一次Navigation流程,

二來可以讓用戶直覺的操作內容。

 

但使用Popup Control就只有好處沒有需要改變的地方嗎?其實是有的,當Popup Control使用時,它是直接覆蓋在目前畫面

中的最上層,因此,在撰寫程式時就需要為了關閉這個Poup Control多做一些處理,例如:按下back鍵把PopupControl關閉。

 

接下來仔細介紹Popup Control類別提供的內容與相關開發重點:

Popup 類別

它是覆蓋在現有 Silverlight 內容的上方來顯示內容,要注意需在 Silverlight 控制項的界限內。Popup類別通常用於暫時顯示

或快速完成的特定工作內容。因此,Popup類別中放罝的UIElement集合,建議是放置些重要(或必要)的控制項目,讓用戶可

直接了當的閱讀或輸入內容。

(a) Popup類別使用「Child屬性」放置要顯示的UIElement集合,然而要注意的是:「不可以放置已設定x:Name的UIElemet控制項」,

     因為Popup類別是直接加上去畫面上,因此,可能發生視覺化樹狀結構中存在兩個名稱相同的項目,這將會出現Exception。

     透過下圖來示意Popup類別加入至現有的樹狀結構為何:

     01

(b) Popup類別是以左上角為依據加入內容,可配合VerticalOffsetHorizontalOffset二個屬性來操作。如下圖:

      00

大概了解Popup類別大致上的用法之後,接下來介紹幾個在開發上常用的屬性:

(a) 常用屬性表:

名稱 描述
Child 取得或設定快顯視窗中要裝載 (Host) 的內容。放置要呈現於Popup類別中的UIElement,通常會自訂UserControl來使用。
IsOpen 取得或設定此快顯視窗目前是否顯示在螢幕上的值。true:代表顯示;false:代表取消。
DataContext 在 FrameworkElement 參與資料繫結時取得或設定其資料內容。
Dispatcher 取得與這個物件關聯的 Dispatcher。透過Application可以直接取得。
HorizontalOffset 取得或設定 Silverlight 控制項左邊與快顯視窗左邊之間的距離。
VerticalOffset 取得或設定 Silverlight 控制項的頂端與快顯視窗的頂端之間的距離。
RenderTransform 取得或設定轉換資訊,該資訊會影響 UIElement 的呈現位置。支援識別目前Popup類別所在的實際Poisition。配合Point類別的使用,即可算出目前實際呈現的位置。
Opacity 取得或設定物件的不透明度。使用Popup類別建議可以使用Opactiy讓呈現於畫面上的內容,隱約可以看到背後的內容,這樣可提供用戶比較容易理解現在要操作的內容。

上述整理的屬性表,是目前我在學習中最常用到的地方,透過IsOpen來決定內容是否要顯示,然而RenderTransform是比較常

看到的部分,不過它可以有效算出目前UIElement在整個Page中的Position。在下方有提供範例的使用方法。

 

(b) 重要方法/事件:

名稱 描述
UpdateLayout 確認 UIElement 的所有子物件位置都已正確為配置而更新。常用於更新畫面中的內容。
CaptureMouse 設定 UIElement 的滑鼠捕捉。如果需要針對用戶於操作上需要補捉Mouse事件,可以啟動該方法
ReleaseMouseCapture 釋放 UIElement 的滑鼠捕捉的事件。與CaptureMouse是一組的。
AddHandler 針對指定的路由事件加入路由事件處理常式,以便將該處理常式加入至目前項目上的事件處理常式集合。 將 handledEventsToo 指定為 true,以針對已經由事件路由上另一個項目標記為已處理的路由事件,叫用提供的處理常式。
RemoveHandler 從這個 UIElement 移除指定的路由事件處理常式。

針對Handler的使用,下方的範例是直接另外自訂一個Handler來使用,其實如果需要增加Popup類別有額外自訂的Handler,

透過AddHandler與RemoveHandler一樣可以做到相同的效果,但要注意的是Delegate的使用。

 

〉範例說明 - 使用Popup Control模擬Dropdownlist

透過一個TextBox加上一個自訂的User Control來完成模擬Dropdownlist的效果。觸發的事件在於:當用戶點擊TextBox後,

觸發GotFocus事件,彈出Popup Control的內容,選擇Popup中的內Listbox,並回傳至TextBox中。以下將透過程式來加以說明:

 

1. 自訂User Control.xaml:

   1: <!-- 自訂User Control並放置一個ListBox -->
   2: <UserControl x:Class="PopupControlPractice.CusControl.PageList"
   3:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   4:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   5:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   6:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   7:     mc:Ignorable="d"
   8:     FontFamily="{StaticResource PhoneFontFamilyNormal}"
   9:     FontSize="{StaticResource PhoneFontSizeNormal}"
  10:     Foreground="{StaticResource PhoneForegroundBrush}"
  11:     d:DesignHeight="480" d:DesignWidth="480" Height="382">
  12:     
  13:     <StackPanel x:Name="LayoutRoot" Background="#FF473B3B" Opacity="0.795" HorizontalAlignment="Center" VerticalAlignment="Center" Height="350">
  14:         <ListBox Name="listBox1" Width="460" SelectionChanged="listBox1_SelectionChanged" Height="400">
  15:             <ListBoxItem Content="Taiwan" FontSize="36" />
  16:             <ListBoxItem Content="Taipei" FontSize="36" />
  17:             <ListBoxItem Content="Taichung" FontSize="36" />
  18:             <ListBoxItem Content="台灣" FontSize="36" />
  19:             <ListBoxItem Content="台北" FontSize="36" />
  20:             <ListBoxItem Content="高雄" FontSize="36" />
  21:             <ListBoxItem Content="台南" FontSize="36" />
  22:             <ListBoxItem Content="台中" FontSize="36" />
  23:             <ListBoxItem Content="新北" FontSize="36" />
  24:         </ListBox>
  25:     </StackPanel>
  26: </UserControl>

 

2. 自訂User Control.cs:

   1: public partial class PageList : UserControl
   2: {
   3:     //Popup control類別
   4:     private Popup gPopupControl;
   5:     //獨立宣告一個SelectionChangedEventHandler事件
   6:     public event SelectionChangedEventHandler PageListSelectHandler;
   7:  
   8:     public PageList()
   9:     {
  10:         InitializeComponent();          
  11:     }
  12:  
  13:     //該方法用於告知Popup Control要產生的Position
  14:     public void Create(double x, double y)
  15:     {
  16:         gPopupControl = new Popup();
  17:         gPopupControl.Child = this;
  18:  
  19:         gPopupControl.IsOpen = true;
  20:         //設定X與Y軸
  21:         gPopupControl.HorizontalOffset = x + 5;
  22:         gPopupControl.VerticalOffset = y + 25;
  23:     }
  24:  
  25:     private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
  26:     {
  27:         //當觸發選取事件後,將剛獨立宣告的SelectionChangedEventHandler事件往上層推送
  28:         SelectionChangedEventHandler tHandler = this.PageListSelectHandler;
  29:         if (tHandler != null)
  30:             tHandler.Invoke(sender, e);
  31:         gPopupControl.IsOpen = false;
  32:     }
  33: }

 

3. 在主畫面中的TextBox加上GotFocus事件與接收SelectionChangedEventHandler事件的處理:

   1: private void textBox1_GotFocus(object sender, RoutedEventArgs e)
   2: {
   3:     //透過GeneralTransform取得目前TextBox的位置資訊
   4:     GeneralTransform tTransform = base.TransformToVisual(textBox1);
   5:     //轉換Transform為實際的Point
   6:     Point tPoint = tTransform.Transform(new Point(0.0, 0.0));
   7:     //宣告Popup Control類別
   8:     CusControl.PageList tList = new CusControl.PageList();
   9:     //設定Popup Control類別要出現的Position
  10:     tList.Create(textBox1.Margin.Left + Math.Abs(tPoint.X),
  11:                  textBox1.Margin.Top + textBox1.Height + Math.Abs(tPoint.Y));
  12:     //註冊處理EventHandler
  13:     tList.PageListSelectHandler += new SelectionChangedEventHandler(tList_PageListSelectHandler);
  14: }
  15:  
  16: void tList_PageListSelectHandler(object sender, SelectionChangedEventArgs e)
  17: {
  18:     ListBoxItem tObject = e.AddedItems[0] as ListBoxItem;
  19:  
  20:     textBox1.Text = tObject.Content.ToString();
  21: }

 

4. 執行結果:

02

======

以上是介紹Popup Control類別的使用,讓在開發WP7時,針對一些比較只是提示型的內容,除了可以透過WP7的ContextMenu類別之外,

也提供另一種透過Popup Control達到的效果。不過透過Popup Control要特別注意產生Popup Control物件的情況,例如:產生完的物件要

如何關閉,要透過Back鍵還是Popup Control中自訂Button來關閉等,這些都會影響畫面中呈現與用戶操作的習慣。

 

References:

Creating a custom popup in Windows Phone 7

Windows Phone 7 Quick Tip #5 – Dismissing Popups Controls

Playing with the Popup Control (必看)

System.Windows.Controls.Primitives 命名空間

PopUp Control In Silverlight (必看)

Tutorial: Create a Silverlight 2 User Control from a Popup Control

Multiline textbox in Windows Phone 7

How to get screen size on Windows Phone 7 Series?

WP7 LongListSelector in depth | Part1: Visual structure and API & Part2 (補充)

Using the LongListSelector control on Windows Phone 7 (補充)

Rectangle in Silverlight & Draggable Popup Window in Silverlight 3

How to position popup control? (重要)

 

Dotblogs Tags: ,