Windows Phone 7.5資料繫結

by Vivid 9. 五月 2012 03:36

.NET Magazine國際中文電子雜誌
者:許薰尹
稿:張智凱
文章編號:N120512401
出刊日期: 2012/5/09

Windows Phone 7.5應用程式是以Silverlight為基礎,Silverlight以XAML來設計使用者介面,因此Windows Phone 7.5應用程式可以透過資料繫結功能,將資料顯示在XAML項目上。本文將介紹基本的資料繫結(Data Binding)設計。

繫結到Silverlight Element

你可以將Silverlight項目的屬性,繫結到另一個Silverlight項目的屬性上。例如你可以將TextBox的Text屬性繫結到TextBlock的Text屬性。當TextBox的內容變動時,TextBlock也可以馬上看到更新的內容。

若要設定繫結,可以使用Visual Studio 2010開發工具,透過屬性視窗,來進行設定的動作。舉例來說,以下有一個TextBox與TextBlock的XAML標籤:

<TextBox Height="72" HorizontalAlignment="Left" Margin="87,49,0,0" Name="textBox1" Text="TextBox" VerticalAlignment="Top" Width="460" />
<TextBlock Height="30" HorizontalAlignment="Left" Margin="95,192,0,0" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" />

要想將TextBlock的Text屬性繫結到TextBox的Text屬性,可以從屬性視窗選取TextBlock的Text屬性後方之「Advanced Options」項目,從突顯式選單中,選取「Apply Data Binding」,參考圖1所示:

clip_image002

圖 1:Apply Data Binding。

在Source區段中,設定ElementName繫結到textBox1,參考圖2所示:

clip_image004

圖 2:設定Source。

然後在Path區段中,設定Text屬性,參考圖3所示:

clip_image006

圖 3:設定Path。

此時Visual Studio 2010會自動產生以下資料繫結的語法:

<TextBox Height="72" HorizontalAlignment="Left" Margin="87,49,0,0" Name="textBox1" Text="TextBox" VerticalAlignment="Top" Width="460" />

<TextBlock Height="30" HorizontalAlignment="Left" Margin="95,192,0,0" Name="textBlock1" Text="{Binding ElementName=textBox1, Path=Text}" VerticalAlignment="Top" />

 

當你執行程式之後,每當在文字方塊輸入資料時,TextBlock會馬上顯示相同的資料,參考圖4所示。

clip_image008

圖 4:資料繫結範例執行結果。

繫結到自訂類別

若類別的屬性要繫結到Silverlight物件,則類別需要實作INotifyPropertyChanged介面,此介面包含一個PropertyChanged事件,定義如下:

public interface INotifyPropertyChanged
{
    event PropertyChangedEventHandler PropertyChanged;
}

PropertyChangedEventHandler是定義在System.ComponentModel命名空間之下,Silverlight項目會使用PropertyChangedEventHandler來管理事件。當繫結到此類別屬性的值變動時,透過PropertyChangedEventHandler來告知屬性變動了。底下的MyCustomClass類別定義中,實作了INotifyPropertyChanged介面,類別包含ID、Name兩個屬性,屬性的set存取子中屬性值變動後,都會觸發PropertyChanged事件:

namespace PhoneApp1
{
    public class MyCustomClass : INotifyPropertyChanged
    {
        private int _ID;

        public int ID
        {
            get { return _ID; }
            set
            {
                _ID = value;
                if ( PropertyChanged != null )
                {
                    PropertyChanged(this , new PropertyChangedEventArgs("ID"));
                }
            }
        }

        private string _Name;

        public string Name
        {
            get { return _Name; }
            set
            {
                _Name = value;
                if ( PropertyChanged != null )
                {
                    PropertyChanged(this , new PropertyChangedEventArgs("Name"));
                }
            }
        }
     

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

 

繫結到自訂類別-在XAML引用命名空間

若要在XAML中繫結到物件,需要在XAML檔案中先引用類別的命名空間。例如想在MainPage.xaml檔案內的XAML標籤中引用MyCustomClass類別所在的PhoneApp3命名空間,可以在<phone:PhoneApplicationPage> 開頭標籤上進行設定,參考以下引用PhoneApp3命名空間的語法,並將此命名空間取一個前置名稱叫「local」:

<phone:PhoneApplicationPage
xmlns:local="clr-namespace:PhoneApp3"

接下來,你需要將類別定義成資源,在<phone:PhoneApplicationPage>開頭標籤下,加上Resources定義:

<phone:PhoneApplicationPage.Resources>
<local:MyCustomClass x:Key="MyCustomClass" />
</phone:PhoneApplicationPage.Resources>

繫結到自訂類別-新增類別到頁面中的項目

有了命名空間之後,你就可以繫結XAML中的項目到此類別,例如以下語法,設定Grid項目繫結到MyCustomClass類別:

<Grid x:Name="LayoutRoot" Background="Transparent"
DataContext="{StaticResource MyCustomClass}"

>

若Grid項目繫結到MyCustomClass類別,則包含在Grid中的任何項目都會自動繫結到此類別,例如以下Grid項目中包含一個TextBox與一個TextBlock,透過Binding物件設定繫結:

<Grid DataContext="{StaticResource MyCustomClass}" x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBox Height="72" HorizontalAlignment="Left"
Margin="76,73,0,0" Name="textBox1"
Text="{Binding Path=Name, Mode=TwoWay}"
VerticalAlignment="Top" Width="460" />

            <TextBlock Height="30" HorizontalAlignment="Left"
Margin="89,193,0,0" Name="textBlock1"
Text="{Binding Path=ID}" VerticalAlignment="Top" />

</Grid>

 

資料繫結可以是單向的,也可以是雙向的。若使用Visual Studio 2010屬性視窗設定繫結,要將TextBox的Text屬性,繫結到MyCustomClass的Name屬性,設定步驟參如下,從Visual Studio 2010屬性視窗選取TextBox的Text屬性後方的「Advanced Options」項目,從突顯式選單中,選取「Apply Data Binding」,,參考圖5所示。

clip_image010

圖 5:套用資料繫結。

因為TextBox是存在於Grid之中,所以Visual Studio 2010會自動參考Grid的設定,將Source設定為「MyCustomClass」;你可以設定Path繫結到Name屬性,參考圖6所示:

clip_image012

圖 6:設定Path。

從「Options」頁可以設定繫結的方向性,例如下圖所示,TextBox的預設繫結方向為雙向繫結(TwoWay) ,參考圖7所示:

clip_image014

圖 7:設定繫結方向。

若使用TextBlock進行繫結,預設繫結的方向性是單向繫結(OneWay)。

繫結到自訂類別-使用程式設定DataContext

若要初始化用來進行資料繫結的物件,您可以在MainPage類別的建構函式進行初始化動作,例如以下的程式範例:

namespace PhoneApp3
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage ( )
        {
            InitializeComponent();
            MyCustomClass c = new MyCustomClass();
            c.ID=100;
            c.Name="Annie";
            ContentPanel.DataContext = c;
           
        }       
    }
}

執行結果參考下圖:

clip_image016

圖 8:資料繫結執行結果。

繫結到清單

有時你的Silverlight應用程式可能會需要顯示清單類型的資料,你可以定義一個類別來存放清單資料,例如以下程式碼建立一個Employees類別,其中包含一個Items屬性,用來存放Employee物件,我們在Employees類別的建構函式中,建立三個Employee資料:

namespace PhoneApp3
{
    public class Employees
    {
        List<Employee> data = null;
        public List<Employee> Items { get { return data; } set { data = value; } }
        public Employees ( )        {
            data = new List<Employee>();
            data.Add(new Employee() { ID = 1 , Name = "Mary" });
            data.Add(new Employee() { ID = 2 , Name = "Candy" });
            data.Add(new Employee() { ID = 3 , Name = "Betty" });
        }               
    }
    public class Employee
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

若XAML中包含一個名為ContentPanel的StackPanel:

<StackPanel x:Name="ContentPanel" Margin="0,8" Grid.Row="1"> </StackPanel>

我們可以在PhoneApplicationPage的Loaded事件進行初始化動作,利用foreach迴圈取出所有Employees中的Employee物件,並將Name屬性值讀出後放在動態建立的TextBlock,再將TextBlock加到ContentPanel.Children集合中顯示:

public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage ( )
        {
            InitializeComponent();           
        }

        Employees empList = null;
        private void PhoneApplicationPage_Loaded ( object sender , RoutedEventArgs e )
        {
            empList = new Employees();
            foreach ( Employee emp in empList.Items)
            {
                TextBlock txt = new TextBlock();
                txt.Text = emp.Name;
                ContentPanel.Children.Add(txt);
            }
        }
    }

 

參考以下資料顯示的結果:

clip_image018

圖 9:繫結到清單。

繫結到清單-使用ListBox顯示清單資料

當然要顯示清單資料有更簡單的選擇:使用ListBox控制項。若XAML中包含一個StackPanel與ListBox:

<StackPanel x:Name="ContentPanel" Margin="0,8" Grid.Row="1" >
<ListBox Height="276" Name="listBox1" Width="460" />
</StackPanel>

然後在PhoneApplicationPag類別的Loaded事件中,加入初始化程式碼

public partial class Page1 : PhoneApplicationPage
    {
        Employees empList = null;
        public Page1 ( )
        {
            InitializeComponent();

        }

        private void PhoneApplicationPage_Loaded ( object sender , RoutedEventArgs e )
        {
            if ( empList == null )
            {
                empList = new Employees();

                foreach ( Employee emp in empList.Items )
                {
                    listBox1.Items.Add(emp.ID.ToString() + "," + emp.Name);
                }
            }       

        }
    }

 

繫結到清單-使用DataTemplate顯示資料

ListBox支援使用資料樣板(Data Template)來顯示資料。資料樣版(Data Template)是由XAML標籤組成,用來定義資料展現的方式,例如要使用TextBox或TextBlock或其它控制項來顯示資料,資料顯示時的前景顏色、背景顏色、框線樣式等等外觀。我們可以自行定義DataTemplate中的內容,選取喜好的方式設定資料的展現。

例如,設計ListBox的資料樣版如下,注意DataTemplate要定義在ListBox的ItemTemplate屬性之中:

<ListBox Name="listBox1"   Height="200"   >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding ID}"/>
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

然後利用PhoneApplicationPage的Loaded事件初始化Employees物件,並將List<Employee> 物件指定給ListBox的ItemsSource屬性來顯示資料:

Employees empList = null;
        private void PhoneApplicationPage_Loaded ( object sender , RoutedEventArgs e )
        {
            if ( empList == null )
            {
                empList = new Employees();
                listBox1.ItemsSource = empList.Items;
            }
        }

執行結果參考圖10所示:

clip_image020

圖 10:使用ListBox顯示資料。

繫結到清單-使用Style顯示資料

你可以使用Style來設定資料展現的樣式,Windows Phone內建許多不同的Style,參考圖11所示:

clip_image022

圖 11:設定Style。

我們可以在DataTemplate中的控制項套用這些內建的Style,例如以下XAML標籤,將第一個TextBlock,套用PhoneTextLargeStyle;第二個TextBlock,套用PhoneTextSubtleStyle:

<ListBox Name="listBox1"   Height="200"   >
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding ID}" Style="{StaticResource PhoneTextLargeStyle}" />
                            <TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextSubtleStyle}" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

畫面參考如下:

clip_image024

圖 12:設定Style顯示資料。

繫結到清單-選取資料

若使用者選取ListBox中的資料,將會觸發ListBox的SelectionChanged事件,你可以撰寫事件處理常式,來做因應的處理。若要產生ListBox的SelectionChanged事件處理常式,只要在屬性視窗,雙擊SelectionChanged,參考圖13所示:

clip_image026

圖 13:SelectionChanged事件。

以下程式碼範例在SelectionChanged事件處理常式中,利用ListBox的SelectedItem屬性找出被選取的Employee物件,然後利用訊息方塊顯示Employee的Name屬性:

private void listBox1_SelectionChanged ( object sender , SelectionChangedEventArgs e )
        {
            Employee emp = listBox1.SelectedItem as Employee;
            MessageBox.Show(emp.Name);
        }

參考以下執行結果:

clip_image028

圖 14:使用MessageBox顯示資料。

繫結到圖片

有時你可能想要顯示圖片的資訊,在Windows Phone應用程式之中,若想要顯示圖片,只需要在設計畫面之中,加入一個Image控制項,然後設定Source屬性為圖檔的名稱即可,例如以下範例:

<Image Height="150" Name="image1" Stretch="Fill" Width="200" Source="1.jpg" />

不過,若在資料繫結應用程式之中,想要顯示圖片,你可以在資料來源的類別中,加入一個屬性來指定圖片的名稱即可,例如延續前文的範例,在Employee類別中定義一個ImageID屬性。

public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string ImageID { get; set; }
}

然後改寫Employees類別,初始化Employee物件時,設定ImageID為圖檔的名稱:

public class Employees
    {
        List<Employee> data = null;
        public List<Employee> Items { get { return data; } set { data = value; } }
        public Employees ( )
        {
            data = new List<Employee>();
            data.Add(new Employee() { ID = 1 , Name = "Mary" ,ImageID="1.Jpg" });
            data.Add(new Employee() { ID = 2 , Name = "Candy" , ImageID = "2.Jpg" });
            data.Add(new Employee() { ID = 3 , Name = "Betty" , ImageID = "3.Jpg" });
        }
    }

最後在ListBox之中加入一個Image控制項,繫結到ImageID屬性,參考以下資料樣版的定義:

<ListBox Height="358" Name="listBox1" Width="460" SelectionChanged="listBox1_SelectionChanged">
             <ListBox.ItemTemplate>
                 <DataTemplate>
                     <StackPanel>
                         <TextBlock Text="{Binding ID}" Style="{StaticResource PhoneTextLargeStyle}" />
                         <TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextSubtleStyle}" />
                         <Image Source="{Binding ImageID}" />
                     </StackPanel>
                 </DataTemplate>
             </ListBox.ItemTemplate>
         </ListBox>

這樣,就可以順利地顯示圖片的資料。不過,回顧此範例程式,若Employee的照片命名原則為:員工的ID.jpg檔,例如ID為1的員工,其圖檔名稱為1.jpg檔案。如此,ID與ImageID的內容大部份重複了,似乎不太需要為Employee類別新增一個ImageID的屬性,針對這個問題,我們可以利用Converter來解決,只要寫一個Converter類別,將「ID」轉換成「 ID.JPG」字串就行了。

底下是一個自訂的MyConverter類別,實作了IValueConverter介面,這個介面包含Convert與ConvertBack兩個方法。Convert方法傳入的第一個value參數代表要轉換的值(value),在此範例中直接讀取value,把轉換完的結果當做Convert方法的回傳值傳回,因此只需要將Employee的ID屬性轉換成字串,再串接「.jpg」回傳。而此範例不需要實作ConvertBack方法,方法直接回傳null。

public class MyConverter : IValueConverter
  {
      public object Convert ( object value , Type targetType , object parameter , System.Globalization.CultureInfo culture )
      {
          string s = value + ".jpg";
          return s;
      }
      public object ConvertBack ( object value , Type targetType , object parameter , System.Globalization.CultureInfo culture )
      {
          return null;
      }
  }

在ListBox資料樣板中,加入一個Image控制項,讓Source繫結到ID屬性。若使用Visual Studio 2010的屬性視窗來設定Source屬性,你可能無法利用視覺化的方式,選到ID屬性,這時不用擔心,直接在XAML編輯畫面中,設定Source為「{Binding ID}」,如下所示:

<ListBox Height="358" Name="listBox1" Width="460" SelectionChanged="listBox1_SelectionChanged">
             <ListBox.ItemTemplate>
                 <DataTemplate>
                     <StackPanel>
                         <TextBlock Text="{Binding ID}" Style="{StaticResource PhoneTextLargeStyle}" />
                         <TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextSubtleStyle}" />
                        <Image Source="{Binding ID}" />

                     </StackPanel>
                 </DataTemplate>
             </ListBox.ItemTemplate>

接下來我們再透過Visual Studio 2010屬性視窗來完成其它部分的設定,選取設計畫面上的Image控制項,再選取屬性視窗Text屬性-「Advanced Options」項目,從突顯式選單中,選取「Apply Data Binding」;然後在「Converter」區段設定Converter為「MyConverter」,然後點選右方Resources區段的「Create New」超連結,便會自動跳出一個「Create Resource」對話盒,為Resource定義一個Key之後,按下「OK」按鈕:

clip_image030

圖 15:設定Converter。

Visual Studio 2010會在XAML中加入以下資源定義的標籤:

<phone:PhoneApplicationPage.Resources>
<my:MyConverter x:Key="MyConverter1" />
</phone:PhoneApplicationPage.Resources>

然後為ListBox設定套用Converter的資料繫結語法:

<ListBox Height="276" Name="listBox1" Width="460" SelectionChanged="listBox1_SelectionChanged">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="{Binding ID}" Style="{StaticResource PhoneTextLargeStyle}" />
                        <TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextSubtleStyle}" />
                           <Image Source="{Binding Path=ID, Converter={StaticResource MyConverter1}}" Width="124" Height="124" Stretch="Fill" />

                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

參考執行結果如圖16所示:

clip_image032

圖 16:繫結到圖片。

總結

本文簡單介紹在Windows Phone 7.5應用程式中,如何利用Visual Studio 2010的屬性視窗來設定資料繫結。透過資料繫結,可以將兩個Silverlight Element項目的屬性連結在一起。此外,您也可以繫結到自訂類別,或將圖片透過資料繫結技術顯示在畫面上。

範例下載: 3_PhoneApp3.rar (182.34 kb)

Tags:

.NET Magazine國際中文電子雜誌 | WindowsPhone | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List