[WP8.1UI控件編程]Windows Phone理解和運用ItemTemplate、ContentTemplate和DataTemplate

2.2.5 ItemTemplate、ContentTemplate和DataTemplate

    在理解ItemTemplate、ContentTemplate和DataTemplate的關係的以前,咱們先來看看ContentControl類和ItemsControl類。ContentControl類是內容控件的基類,如Button, CheckBox,最明顯的特徵就是這個控件有Content屬性,有Content屬性的系統控件都是ContentControl的子類。ItemsControl類是列表內容控件的基類,如ListBox,它和ContentControl類是相似的,只不過ContentControl類是單項的內容,ItemsControl是多項的內容。html

    那麼全部繼承自ContentControl的內容控件的ContentTemplate屬性和全部繼承自ItemsControl的列表控件的ItemTemplate屬性,都是DataTemplate類型的,意思就是咱們能夠經過DataTemplate來定義ContentControl和ItemsControl的控件的UI效果和數據的顯示。編程

2.2.6 數據模板的使用

    DataTemplate是一種可視化的數據模板,它強大的做用在於能夠把數據經過綁定的方式展示到控件上。在上面的例子中,咱們介紹了用DataTemplate去實現了UI控件的內容的顯示,那麼其實DataTemplate最主要的做用並非去取代ControlTemplate的樣式定義,而是經過數據綁定把數據的控件的數據源的信息展示到控件上。app

    下面咱們仍是經過一個Button的控件來看一下DataTemplate的數據綁定是如何發揮做用的。字體

    代碼清單2-5數據模板(源代碼:第2章\Examples_2_5)spa

    (1)首先定義一個Person類表示是數據實體的類型,代碼以下:設計

    public class Person
    {
        public string LastName { get; set; }
        public string FirstName { get; set; }
    }

 

    (2)設計一個DataTemplate,並把這個DataTemplate做爲一個資源來使用,這是和Style資源是同樣的道理,DataTemplate也能夠做爲公共的資源給多個控件去使用。那麼這個模板的內容是使用StackPanel控件把Person對象的信息水平排列起來。code

    < Page.Resources>
        <DataTemplate x:Key="PersonNameDataTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding LastName}"/>
                <TextBlock Text=", "/>
                <TextBlock Text="{Binding FirstName}"/>
            </StackPanel>
        </DataTemplate>
    </ Page.Resources>

 

    (3)建立一個Button控件,把ContentTemplate屬性和模板資源關聯起來。htm

     <Button  x:Name="singlePersonButton"  ContentTemplate="{StaticResource PersonNameDataTemplate}"/>

 

    (4)建立一個Person對象而且賦值給Button控件的Content屬性。對象

    singlePersonButton.Content = new Person { FirstName = "lee", LastName = "Terry" };blog

    最後咱們能夠看到按鈕的運行效果如圖2.14所示,DataTemplate能夠把數據對象綁定起來來實現更加靈活的通用的強大的UI數據顯示效果。

 

     圖2.14 數據模板綁定的按鈕

    那麼剛纔的示例是DataTemplate在ContentControl類型的控件上的應用,那麼下面咱們再來看看DataTemplate在ItemsControl類型的控件上的實現,ContentControl和ItemsControl也是能夠直接做爲控件去使用的,若是咱們並不須要Button或者ListBox這些控件的一些高級功能,就能夠直接使用ContentControl或者ItemsControl控件。

    (1)定義一個ItemsControl控件,把ItemTemplate屬性和模板資源關聯起來。

<ItemsControl     x:Name="itemsControl" ItemTemplate="{StaticResource     PersonNameDataTemplate}" />

    (2)建立一個Person對象的集合而且賦值給ItemsControl控件的ItemsSource屬性。

        Persons.Add(new Person { FirstName = "lee2", LastName =     "Terry2" });   

        Persons.Add(new Person { FirstName = "lee3", LastName =     "Terry3" });

        Persons.Add(new Person { FirstName = "lee4", LastName =     "Terry4" });  

        Persons.Add(new Person { FirstName = "lee5", LastName =     "Terry5" });

        itemsControl.ItemsSource = Persons;

    這時候能夠看到運行效果如圖2.15所示,ItemsControl能夠把數據集合經過列表的形式展示出來,可是你會發現直接用ItemsControl實現的列表的功能很是有限,而且也不能滾動,接下來再結合一下ContentTemplate來進行完善這個列表的控件。

 

   圖2.15 數據模板綁定的列表

    (3)定義一個ItemsControl的樣式,其實就是自定義一個ControlTemplate的模板做爲ItemsControl控件的模板來使用,那麼這個模板就是一個內容的展示形式的模板。咱們在ControlTemplate模板上定義了一個ScrollViewer控件而後裏面再使用了一個StackPanel控件,最裏面的是ItemsPresenter控件。列表的DataTemplate的顯示內容就是直接投影在ItemsPresenter控件上面的。咱們對ScrollViewer控件和StackPanel控件都設置了不一樣的邊框顏色,這樣在運行的時候就能夠很明顯地看出來控件之間的關係是怎樣的。

<Style x:Name="ItemsControlStyle"     TargetType="ItemsControl">
   
            <Setter Property="Template">
   
            <Setter.Value>
   
                <ControlTemplate     TargetType="ItemsControl">
   
                    <ScrollViewer     BorderBrush="Red" BorderThickness="6">
   
                        <StackPanel     Orientation="Horizontal" Background="Blue">
   
                            <Border     BorderBrush="Yellow" BorderThickness="3">
   
                            <ItemsPresenter     />
   
                            </Border>
   
                        </StackPanel>
   
                    </ScrollViewer>
   
                </ControlTemplate>
   
            </Setter.Value>
   
            </Setter>
   
        </Style>
   

 

    (4)在ItemsControl上添加Style屬性爲上面定義的樣式。

      <ItemsControl x:Name="itemsControl"     ItemTemplate="{StaticResource PersonNameDataTemplate}"     Style="{StaticResource ItemsControlStyle}"/>

 

 

    程序的運行效果如圖2.16所示。

 

圖2.16 列表控件的各個模塊

2.2.7 讀取和更換數據模板

    對於系統的樣式,咱們能夠經過在C#代碼裏面讀取出來而後再修改,實現動態更換主題的目的。那麼技術老是相通的,對於控件的DataTemplate,咱們同樣也能夠經過C#代碼去讀取出來,而後動態地更換,實現更加豐富和靈活化的樣式展現方案。在C#代碼裏面讀取和更換數據模板也是經過對ContentTemplate屬性進行讀取和賦值就能夠了。

    這種讀取和更換數據模板在列表的控件中會比較常見,好比我要實現一個這樣一個功能,經過一個列表展示出一批數據,用戶打擊某一條數據的時候,這條數據的樣式要發生改變,表示選取了這條數據,而後用戶能夠取消這條數據的選擇也能夠繼續選擇多條數據。那麼這樣的功能在數據多選的狀況下是很是廣泛的功能來的。下面咱們來實現這樣的一個功能。

    代碼清單2-6動態更換樣式(源代碼:第2章\Examples_2_6)

    (1)定義3個DataTemplate資源,一個是非選中狀態,一個是選中狀態的,還有一個是默認的狀態,其實默認的狀態和非選中狀態是同樣的,可是由於默認的狀態的數據項樣式不能在C#裏面再次調用。在兩個模板中都添加了Tap事件,用戶捕獲用戶的點擊事件。數據源集合與上一個例子同樣。

    < Page.Resources>
        <!--選中數據項的樣式-->
        <DataTemplate x:Key="dataTemplateSelectKey" x:Name="dataTemplateSelectName">
            <Grid  Tapped="StackPanel_Tap_1" Background="Red">
                <TextBlock Text="{Binding LastName}" FontSize="50" />
            </Grid>
        </DataTemplate>
        <!--默認數據項的樣式,注意默認的數據項樣式不能在C#中再次調用-->
        <DataTemplate x:Key="dataTemplateDefaultKey" x:Name=" dataTemplateDefaultName">
            <StackPanel Orientation="Horizontal" Tapped ="StackPanel_Tap_1">
                <TextBlock Text="{Binding LastName}"/>
                <TextBlock Text=", "/>
                <TextBlock Text="{Binding FirstName}"/>
            </StackPanel>
        </DataTemplate>
        <!--非選中數據項的樣式-->
        <DataTemplate x:Key="dataTemplateNoSelectKey" x:Name="dataTemplateNoSelectName">
            <StackPanel Orientation="Horizontal" Tapped ="StackPanel_Tap_1">
                <TextBlock Text="{Binding LastName}"/>
                <TextBlock Text=", "/>
                <TextBlock Text="{Binding FirstName}"/>
            </StackPanel>
        </DataTemplate>
    </ Page.Resources>
    ……省略若干代碼
    //建立ItemsControl控件來綁定列表的數據
    <ItemsControl  x:Name="listbox" ItemTemplate="{StaticResource dataTemplateDefaultKey }"/>

 

    (2)處理點擊事件,判斷當前控件的模板和從新賦值模板。能夠經過Name屬性訪問XAML中定義的DataTemplate。

    private void StackPanel_Tap_1(object sender, TappedRoutedEventArgs e)
    {
        // 獲取ItemsControl對象的ItemContainerGenerator屬性
        // 經過點擊的控件的DataContext判斷所綁定的數據對象
        // 而後從ItemContainerGenerator裏面獲取到當前的ContentPresenter對象
        ContentPresenter myContentPresenter = (ContentPresenter)(listbox.ItemContainerGenerator.ContainerFromItem((sender as Panel).DataContext));
        // 判斷數據模板是選中狀態的仍是非選中狀態的,而後進行賦值
        if (myContentPresenter.ContentTemplate.Equals(dataTemplateSelectName))
        {
            //賦值非選中狀態的模板
            myContentPresenter.ContentTemplate = dataTemplateNoSelectName;
        }
        else
        {
            //賦值選中狀態的模板
            myContentPresenter.ContentTemplate = dataTemplateSelectName;
        }
    }

 

    運行的效果如圖2.17所示,當咱們點擊一下數據項的時候,字體會變大,背景會變成紅色,在點擊一次就會變成原來的樣子。

 

圖2.17 動態更換樣式

    (3)在這裏還要注意一點的是,若是使用的時ListBox控件而不是ItemsControl控件的時候,在獲取ContentPresenter對象的時候須要經過可視化樹去查找。代碼的實現以下所示:

    private void StackPanel_Tap_1(object sender, TappedRoutedEventArgs e)
    {
         //獲取到的對象是ListBoxItem
         ListBoxItem myListBoxItem =  (ListBoxItem)(listbox.ItemContainerGenerator.ContainerFromItem((sender as Panel).DataContext));
         // 在ListBoxItem中查找ContentPresenter
         ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
        ……//省略若干代碼
    }
    //查找可視化樹某個類型的元素
    private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            if (child != null && child is childItem)
                return (childItem)child;
            else
            {
                childItem childOfChild = FindVisualChild<childItem>(child);
                if (childOfChild != null)
                    return childOfChild;
            }
        }
        return null;
    }

本文來源於《深刻理解Windows Phone 8.1 UI控件編程》

源代碼下載:http://vdisk.weibo.com/s/zt_pyrfNHoezI

歡迎關注個人微博@WP林政

WP8.1技術交流羣:372552293

相關文章
相關標籤/搜索