[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是多项的内容。

那么所有继承自ContentControl的内容控件的ContentTemplate属性和所有继承自ItemsControl的列表控件的ItemTemplate属性,都是DataTemplate类型的,意思就是我们可以通过DataTemplate来定义ContentControl和ItemsControl的控件的UI效果和数据的显示。

2.2.6 数据模板的使用

DataTemplate是一种可视化的数据模板,它强大的作用在于可以把数据通过绑定的方式展现到控件上。在上面的例子中,我们介绍了用DataTemplate去实现了UI控件的内容的显示,那么其实DataTemplate最主要的作用并不是去取代ControlTemplate的样式定义,而是通过数据绑定把数据的控件的数据源的信息展现到控件上。

下面我们还是通过一个Button的控件来看一下DataTemplate的数据绑定是如何发挥作用的。

  
 
代码清单2-5数据模板(源代码:第2章\Examples_2_5)

(1)首先定义一个Person类表示是数据实体的类型,代码如下:

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

(2)设计一个DataTemplate,并把这个DataTemplate作为一个资源来使用,这是和Style资源是一样的道理,DataTemplate也可以作为公共的资源给多个控件去使用。那么这个模板的内容是使用StackPanel控件把Person对象的信息水平排列起来。


    < 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属性和模板资源关联起来。

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

(4)创建一个Person对象并且赋值给Button控件的Content属性。

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

最后我们可以看到按钮的运行效果如图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;
}

源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHoezI

[WP8.1UI控件编程]Windows
Phone理解和运用ItemTemplate、ContentTemplate和DataTemplate,布布扣,bubuko.com

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

时间: 2024-10-21 09:54:51

[WP8.1UI控件编程]Windows Phone理解和运用ItemTemplate、ContentTemplate和DataTemplate的相关文章

[WP8.1UI控件编程]Windows Phone动画方案的选择

8.1 动画方案的选择 Windows Phone的动画实现方式有线性插值动画(3种类型).关键祯动画(4种类型)和基于帧动画,甚至还有定时器动画,然后动画所改变的UI元素属性可以是普通的UI元素属性,变换特效属性和三维特效属性,面对着这么多的选择,我们要实现一个动画效果该怎么去思考动画实现的思路以及怎么选择实现的技术呢?那么我们这小节会先讲解与动画性能相关的知识,然后再讲解怎么去选择动画的实现方案. 8.1.1 帧速率 帧速率是用于测量显示帧数的量度,测量单位为"每秒显示帧数"(Fr

[WP8.1UI控件编程]Windows Phone VirtualizingStackPanel、ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件

11.2.2 VirtualizingStackPanel.ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件 VirtualizingStackPanel.ItemsStackPanel和ItemsWrapGrid都是虚拟化布局控件,一般情况下在界面的布局上很少会用到这些虚拟化排列的控件,大部分都是封装在列表的布局面板上使用,主要的目的就是为了实现列表上大数据量的虚拟化,从而极大地提高列表的效率.那么其实这3个虚拟化布局控件都是列表控件的默认布局排列的方式,其中Vir

[WP8.1UI控件编程]Windows Phone大数据量网络图片列表的异步加载和内存优化

11.2.4 大数据量网络图片列表的异步加载和内存优化 虚拟化技术可以让Windows Phone上的大数据量列表不必担心会一次性加载所有的数据,保证了UI的流程性.对于虚拟化的技术,我们不仅仅只是依赖其来给列表加载数据,还可以利用虚拟化的特性去做更多的事情.虚拟化技术有一个很重要的特性就是,它可以准确地判断出哪些列表项处于手机屏幕中,可以动态地去更新这些数据.基于这样的特性,我们可以给列表的功能做更多的优化. 那么下面我们基于一个例子来讲解利用虚拟化技术去做列表的性能优化.有这么一个需求,需要

[WP8.1UI控件编程]Windows Phone自定义布局规则

3.2 自定义布局规则 上一节介绍了Windows Phone的系统布局面板和布局系统的相关原理,那么系统的布局面板并不一定会满足所有的你想要实现的布局规律,如果有一些特殊的布局规律,系统的布局面板是不支持,这时候就需要去自定义实现一个布局面板,在自定义的布局面板里面封装布局规律的逻辑.那么我们这一节从一个实际的需求出发,来实现一个自定义规律的布局面板.我们这一小节要实现的布局规律是把布局面板里面的子元素,按照圆形的排列规则进行排列,下面我们来看下这个例子的详细实现过程. 3.2.1 创建布局类

[WP8.1UI控件编程]Windows Phone XAML页面的编译

1.1.2 XAML页面的编译 Windows Phone的应用程序项目会通过Visual Studio完成XAML页面的编译,在程序运行时会通过直接链接操作加载和解析XAML,将XAML和过程式代码自动连接起来.如果你不在乎将XAML文件和过程式代码融合,那么只需要把它添加到Visual Studio的Windows Phone项目中来,并用界面中的Build动作来完成编译即可,一般公共的样式资源的XAML文件都是采用这种方式.但是如果要编译一个XAML文件并将它与过程式代码混合,第一步要做的

[WP8.1UI控件编程]SemanticZoom控件实现分组列表

11.1.5 SemanticZoom实现分组列表 SemanticZoom控件可以让用户实现一种更加高级的列表,这种列表可以对列表的项目进行分组,同时这个SemanticZoom控件会提供两个具有相同内容的不同视图,其中有一个是主视图,另外一个视图可以让用户进行快速导航的分组视图.例如,Windows Phone里面的人脉通讯录列表就是使用SemanticZoom控件实现的. SemanticZoom控件支持对GridView和ListView控件的视图效果进行缩放,在SemanticZoom

《深入理解Windows Phone 8.1 UI控件编程》基于最新的Runtime框架

<深入理解Windows Phone 8.1 UI控件编程>本书基于最新的Windows Phone 8.1 Runtime SDK编写,全面深入地论述了最酷的UI编程技术:实现复杂炫酷的动画.掌握布局原理.列表虚拟化原理.高性能列表实现.图表编程.控件原理等.  全书源代码免费下载: http://vdisk.weibo.com/s/zt_pyrfNHoezI 试读章节会在博客园持续更新: [WP8.1UI控件编程]Windows Phone XAML页面的编译 [WP8.1UI控件编程]W

《深入理解Windows Phone 8.1 UI控件编程》

<深入理解Windows Phone 8.1 UI控件编程>本书基于最新的Windows Phone 8.1 Runtime SDK编写,全面深入地论述了最酷的UI编程技术:实现复杂炫酷的动画.掌握布局原理.列表虚拟化原理.高性能列表实现.图表编程.控件原理等. 目录如下: <深入理解Windows Phone 8 .1 UI控件编程>目录 第1章 深入解析程序界面 1.1 XAML的原理 1.1.1 XAML的概念 1.1.2 XAML页面的编译 1.1.3 动态加载XAML 1

C# word控件编程

C# word控件WinWordControl可创建.编辑.保存word. 1.使用代码直接创建word文件,同时可以添加页眉.内容.图片及表格,示例代码: /// <summary>        /// 新创建word        /// </summary>        /// <param name="fileSaveDirectory">word保存路径(可默认)</param>        /// <param n