zoukankan      html  css  js  c++  java
  • 《深入浅出WPF》笔记——模板篇

    我们通常说的模板是用来参照的,同样在WPF中,模板是用来作为制作控件的参照。

    一、认识模板

    1.1WPF菜鸟看模板

      前面的记录有提过,控件主要是算法和数据的载体。控件的算法主要体现在可以激发的事件、可以调用的方法、能进行的操作等方面;控件的数据体现为:控件能展示哪些数据。上面两方面终决定了控件,在以前的GUI界面上面,或者是Winform上面,控件的数据和功能耦合的太紧密,如果控件想以不同格式显示数据的话,由于控件的形状基本上都固定了,只有重新去自定义控件,以适合数据的显示格式。在WPF中,就可以让模板出马了,如果你让数据以不同的格式显示,那么直接在数据的外衣——DataTemplate里面定义一些控件,安排好布局,到用的时间,直接给拥有数据的控件穿上衣服,数据控件上面就会参照着我们的模板来显示数据了。当然还有一种情况,我们想让一种控件的显示稍作一点修改,由于传统的控件的主要问题就是耦合性太强,才不易控制,在WPF中,一个控件,可能是多个控件的合体,这样我们就相对更容易控制它。由于控件可以拆分,那么在控件里面添加一个控件或者是对某些控件的属性做些修改,就不需要重新定义控件,只需要定义一个ControlTemlate,然后让其装在Style里面,最后让控件拥有Style——那么控件就会照着ControlTemplate里面的定义来显示。

    1.2容易弄乱的几个单词区分

      由于模板系列的单词很相像,很容易弄乱掉,所以我觉得还是很有必要把几个单词做简要的说明。在区分之前,还是先了解一下Style,因为Style与ControlTemplate的联系比较紧密,为了防止思路死锁,在此稍作说明,具体的用法会在后面详细记录。Style是风格,对于一个风格,为了不至于有的控件使用该风格搞成四不像,如你让涛哥天天穿个背心去开会,那还得了,一定是要穿的庄重吧,同样控件也是如此,要定义风格要有适合的类,也即要定义其目标类型,然后根据目标的属性来定义风格的具体内容。下面给出一个简要的风格定义:

    <Style x:Key="RoundCornerTextBoxStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                              Background
    ="{TemplateBinding Background}" CornerRadius="10" SnapsToDevicePixels="true"> <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>

      接着解释一下上面风格的含义:一个风格如果作为资源可以供多个控件使用的话,就可以使用x:key,BaseOn获取或设置为当前样式的基类型中定义的样式,基类型中有定义,目标类型没有定义的话,会使用基类型的样式。TargetType是目标类型,对于简单的Setter可以直接写成<Setter Property="属性值" Value=“对应的属性值”/>对于复杂的可以通过内容标签的写法如: <Setter Property="BorderBrush" Value="Red"/>就是设置笔刷属性为红色,上面的代码中是设置控件的Template属性,为ControlTemplate类型的值,其中TemplateBinding为绑定目标控件的属性,可以说TemplateBinding是控件专用的,其他和Binding保持一致。

    稍微了解了Style之后再来看DataTemplate和ControlTemplate,他们是控件属性的类型。具体的如下:

    ControlTemplate类的代表:

    • ContentControl类型的Template属性,例如Button为ContentControl类
    • ItemsControl类型的Template属性,例如ListBox为ItemsControl类

    关于两种类型的元素具体可以参考控件和布局的记录。

    DataTemplate的典型代表:

    • ContentControl类型的ContentTemplate属性
    • ItemsControl类型的ItemTemplate属性
    • Gridview的行中的CellTemplate属性

    是不是有点乱了,下面给出一个草图(图1)来表述一下,下面的例子中可能会遇到很多类型名和属性容易混淆的地方,可以回头看一下。

    图1

    二、数据的外衣DataTemplate

      在实际的UI设计中,可能会经常遇到,把已知的数据,通过一定的格式或者是按照一定的排列显示出来,DataTemplate正是解决这样的问题的模板,然后直接把DataTemplate利用空间的属性穿在身上了,最终控件中的数据就会按照一定的排列显示了,最终上了舞台。下面就通过实例来演示一下DataTemplate,该实例涉及到的内容可能比较多,主要包含绑定、资源、ItemsControl、Converter等的使用,如果不懂的话可以留言给我,好了,先看一下效果如图2:

    图2

    左边的是一个UserControl(继承与ContentControl),中间的是ListBox(继承与ItemsControl)。当点击ListBox的项时,可以改变左边的颜色。直接上代码了:

    <Window x:Class="Chapter_09.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:Chapter_09"
            Title="MainWindow" Height="350" Width="450">
        <Window.Resources>
            <local:NoConvertImage x:Key="nci"/>
            <!--定义详细模板-->
            <DataTemplate x:Key="studentDetail">
                <Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
                    <StackPanel Margin="5" Orientation="Vertical">
                        <Image  Source="{Binding No,Converter={StaticResource nci}}" Width="250"/>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Name:" FontWeight="Bold" ></TextBlock>
                            <TextBlock Text="{Binding Name}"></TextBlock>
                            <TextBlock Text="Gender:" FontWeight="Bold" ></TextBlock>
                            <TextBlock Text="{Binding Sex}"></TextBlock>
                            <TextBlock Text="Age:" FontWeight="Bold" ></TextBlock>
                            <TextBlock Text="{Binding Age}"></TextBlock>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="No:" FontWeight="Bold" ></TextBlock>
                            <TextBlock Text="{Binding No}"></TextBlock>
                            <TextBlock Text="Color:" FontWeight="Bold" ></TextBlock>
                            <TextBlock Text="{Binding Color}"></TextBlock>
                        </StackPanel>
                        </StackPanel>
                </Border>
            </DataTemplate>
            <!--定义列表模板-->
            <DataTemplate x:Key="studentList">
                <Grid Margin="2">
                    <StackPanel Orientation="Horizontal">
                        <Image Source="Resources/Images/月饼.png" />
                        <StackPanel>
                            <TextBlock Text="{Binding Name}"></TextBlock>
                            <TextBlock Text="{Binding Color}"></TextBlock>
                        </StackPanel>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </Window.Resources>
        <StackPanel Orientation="Horizontal" >
            <UserControl ContentTemplate ="{StaticResource studentDetail}" Content="{Binding SelectedItem,ElementName=listBox}"/>
            <ListBox x:Name="listBox"  ItemTemplate="{StaticResource studentList}"/>
        </StackPanel>
    </Window>

    后台代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace Chapter_09
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                //绑定ListBox和listViewItem
                InitialStudentList();
            }
            private void InitialStudentList()
            {
                List <Student> studentList= new List<Student>()
                {
                    new Student(){Name="张飞",Age=53,Color="蓝色",No="1",Sex=""},
                    new Student(){Name="貂蝉",Age=53,Color="绿色",No="2",Sex=""},
                    new Student(){Name="曹操",Age=53,Color="红色",No="3",Sex=""},
                    new Student(){Name="华佗",Age=53,Color="橙色",No="4",Sex=""},
                    new Student(){Name="赵云",Age=53,Color="紫色",No="5",Sex=""}
                };
                this.listBox.ItemsSource = studentList;         
            }
        }
    
        #region Student——学生类
        public class Student
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public string No { get; set; }
            public string Sex { get; set; }
            public string Color { get; set; }
        }
        #endregion
    
        #region 把ID转化成Uri形式
        public class NoConvertImage : IValueConverter
        {
            #region IValueConverter 成员
    
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                string uriImg = string.Format(@"/Resources/Images/{0}.png", (string)value);
                return new BitmapImage(new Uri(uriImg, UriKind.Relative));
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
    
            #endregion
        } 
        #endregion
    }

      相对来说,后台代码都是用的以前的知识,前台XAML代码有几点要记录一下:在此处Datatemplate声明为资源,然后通过ContentTemplate,ItemTemplate属性获取到资源。在上面的例子中还有要注意的地方是:UserControl的Content="{Binding SelectedItem,ElementName=listBox}属性为Object类,所以在此绑定ListBox的选定项作为Content,在通过绑定来获取图片和人物的信息,除此还有一个要注意的,还有个是数据驱动,以前我们使用事件驱动应该是通过选项的id来得到Student实体,然后把实体的信息在详情中显示,经过的步骤比较多,可见数据驱动的好处。

     三、控件的外衣——ControlTemplate

       ControlTemplate主要用于改变控件的形状,是对控件已有的形状不满意,通常借助Style来指定目标控件的Template属性来实现。下面我们就来举个例子,来以小见大。该例子是把TextBox的边框改成圆角。本例子要用到Blend工具。

    首先在新建的项目主窗体中添加一个TextBox,然后通过编辑模板->编辑副本(如图3) 

     图3

    然后通过出现一个创建Style资源,选择应用程序,以便其他控件也可以使用,如图4。之后发现转到App.xaml文件里面了。

    图4

      我们暂且不去看代码的意思,我们先看对象和时间线的截图(图5)模板下面有两个控件,但是具有层次关系,这不是我们以前记录的可视树吗?所以为控件指定ControlTemplate衣服,其实就是来修改可视树上的元素。我们把Style部分的代码改为上面介绍Style时引用的代码:

    图5

            <Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
                               Background="{TemplateBinding Background}" CornerRadius="10" SnapsToDevicePixels="true"> <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>

    发现现在主窗体的textBox已经变成椭圆形的了。上面的代码只是让Border代替了原来的控件。然后去掉了Style的触发器(后面会记录到)。关于ControlTemplate,重在编辑里面的元素,以及元素的属性。下面看一下效果:

    图6

     除了上面的两个模板之外还有个是只和ItemsControl有关的PanelTemplate:指定 ItemsPresenterItemsControl 的项的布局创建的面板.也就是指定一个承载ItemsControl的条目的面板,以便使控件的布局更加灵活。例如,我们平时见到的ListBox控件都是竖着下来的,我们下面演示一个横着排列的,其中就利用到了PanelTemplate。代码和效果如图7:

     图7

    此功能不是本记录的重点,所以不做过多介绍。 

     四、DataTeplate的另外几种用法

    4.1设置DataTemplate的DataType属性  

      除了为控件指定DataTeplate,还可以不指定DataTemplate。而是在DataTemplate设置DataType属性,类似于 Style 类的 TargetType 属性的属性。 如果将此属性设置为数据类型,但没有指定 x:KeyDataTemplate 自动应用于该类型的数据对象 。下面的例子是自动的使用于ItemsControl的条目:

    <Window x:Class="WpfControlTemlate.DataTypeOfDataTemplate"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfControlTemlate"
            xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
            Title="DataTypeOfDataTemplate" Height="300" Width="300">
        <Window.Resources>
            <!--会自动的根据数据类型来做适合控件的衣服-->
            <DataTemplate DataType="{x:Type local:Unit}">
                <Grid>
                    <StackPanel Orientation="Horizontal">
                        <Grid>
                            <Rectangle Stroke="Yellow" Fill="Orange" Width="{Binding Price}"/>
                            <TextBlock Text="{Binding Year}"/>
                        </Grid>
                        <TextBlock Text="{Binding Price}"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
            <c:ArrayList x:Key="ds">
                <local:Unit Year="2011年" Price="100"/>
                <local:Unit Year="2010年" Price="120"/>
                <local:Unit Year="2012年" Price="140"/>
                <local:Unit Year="2013年" Price="160"/>
                <local:Unit Year="2014年" Price="180"/>
            </c:ArrayList>
        </Window.Resources>
        <StackPanel>
            <ListBox ItemsSource="{StaticResource ds}"/>
            <ComboBox ItemsSource="{StaticResource ds}" Margin="5"/>
        </StackPanel>
    </Window>

    其中Unit的代码为:

        public class Unit
        {
            public int Price { get; set; }
            public string Year { get; set; }
        }

    效果如图8:

    图8

    4.2DataTemplate对XML的支持

      下面两个例子为两个比较常见的例子(TreeView和Menu),只给出代码和效果图,具体用的时间可以自己去试着修改:

    XML
    <?xml version="1.0" encoding="utf-8" ?>
    <Data xmlns="">
      <Grade Name="一年级">
        <Class Name="甲班">
          <Group Name="A组"/>
          <Group Name="B组"/>
          <Group Name="C组"/>
        </Class>
        <Class Name="乙班">
          <Group Name="A组"/>
          <Group Name="B组"/>
          <Group Name="C组"/>
        </Class>
      </Grade>
      <Grade Name="二年级">
        <Class Name="甲班">
          <Group Name="A组"/>
          <Group Name="B组"/>
          <Group Name="C组"/>
        </Class>
        <Class Name="乙班">
          <Group Name="A组"/>
          <Group Name="B组"/>
          <Group Name="C组"/>
        </Class>
      </Grade>
      <Grade Name="三年级">
        <Class Name="甲班">
          <Group Name="A组"/>
          <Group Name="B组"/>
          <Group Name="C组"/>
        </Class>
        <Class Name="乙班">
          <Group Name="A组"/>
          <Group Name="B组"/>
          <Group Name="C组"/>
        </Class>
      </Grade>
    </Data>
    XAML
    <Window x:Class="WpfControlTemlate.HierarchicalDataTemplate"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="HierarchicalDataTemplate" Height="300" Width="300">
        <Window.Resources>
            <XmlDataProvider x:Key="ds" Source="Data.xml" XPath="Data/Grade"/>
            <!--ItemsSource="{Binding XPath=Class}"表示下一个节点的源-->
            <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">
                <TextBlock Text="{Binding XPath=@Name}"/>
            </HierarchicalDataTemplate>
            
            <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
                <RadioButton Content="{Binding XPath=@Name}" GroupName="gn"/>
            </HierarchicalDataTemplate>
            
            <HierarchicalDataTemplate DataType="Group" >
                <CheckBox Content="{Binding XPath=@Name}" />
            </HierarchicalDataTemplate>
            
        </Window.Resources>
        <Grid>
            <TreeView Margin="5" ItemsSource="{Binding Source={StaticResource ds}}"/>
        </Grid>
    </Window>

    效果如图9

    图9

    XML
    <?xml version="1.0" encoding="utf-8" ?>
    <Data xmlns="">
      <Operation Name="文件" Gesture="F">
        <Operation Name="新建" Gesture="N">
          <Operation Name="项目" Gesture="Control+P"/>
          <Operation Name="网站" Gesture="Control+W"/>
          <Operation Name="文档" Gesture="Control+D"/>
        </Operation>
        <Operation Name="保存" Gesture="S"/>
        <Operation Name="打印" Gesture="P"/>
        <Operation Name="退出" Gesture="X"/>
      </Operation>
      <Operation Name="编辑" Gresture="E">
          <Operation Name="拷贝" Gesture="Control+C"/>
          <Operation Name="剪切" Gesture="Control+X"/>
          <Operation Name="粘贴" Gesture="Control+V"/>
        </Operation>
    </Data>
    XMAL
    <Window x:Class="WpfControlTemlate.MenuTemplate"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MenuTemplate" Height="300" Width="300">
        <Window.Resources>
            <XmlDataProvider x:Key="ds" Source="MenuList.xml" XPath="Data/Operation"/>
    
            <HierarchicalDataTemplate DataType="Operation" ItemsSource="{Binding XPath=Operation}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding XPath=@Name}" Margin="10,0"/>
                    <TextBlock Text="{Binding XPath=@Gesture}"/>
                </StackPanel>
            </HierarchicalDataTemplate>
        </Window.Resources>
        <StackPanel MenuItem.Click="StackPanel_Click">
            <Menu ItemsSource="{Binding Source={StaticResource ds}}"/>
        </StackPanel>
    </Window>

    后台代码是添加了单击事件来获取点击的是哪个菜单选项,我们可以根据其选项作出相应的操作。

    CS
            private void StackPanel_Click(object sender, RoutedEventArgs e)
            {
                MenuItem mi = e.OriginalSource as MenuItem;
                XmlElement xe = mi.Header as XmlElement;
                MessageBox.Show(xe.Attributes["Name"].Value);
            }

    效果如图10

    图10

    五、Style

    5.1Style的Setter

      前面已经稍微理解了一下Style的概念,下面就来记录一下其用法,Setter是设置器的意思。Style有个Setters标签,里面的值为Setter集合。对应的格式为<Setter Property="属性值" Value=“对应的属性值”/>下面来看个例子:

    图11

     其中上面的Setters标签可以省略。通过Style来限制TextBox的格式,如果不想使用的话,可以使用Style=“{x:Null}”。当然Style也可以添加在App.xaml文件中。如果想用style的话可以用<TextBox Text="Hello Style" Style="{DynamicResource textBoxStyle}"/>动态资源来套用。

     5.2  Style中的基本Trigger

       Trigger,触发器,当某些条件满足的时间会触发一个行为。下面先介绍一下基本trigger。Trigger中也有Property和Value,用来限制条件,除此之外还有Setters,表示满足条件呈现的样式。下面的图为当CheckBox选中是字体呈现Orange颜色和20号字体。

    图12

    5.3 Style中的MultiTrigger

      这个触发器不能从名字上面理解,该触发器应该是多条件触发器,是属性满足了条件呈现特点的Style。下面例子为CheckBox选中,且Content为123的显示一定的Style。

    图13

    5.4由数据触发的DataTrigger

       在程序设计中,经常碰到如果客户输入不合法的字符串,要显示文本框为红色,来提醒客户。下面就演示一下具体怎么用:下面的例子为TextBox中的Text长度小于7会让Border保持红色。

    XAML
    <Window x:Class="Style.DataTriggerOfStyle"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:Style"
            Title="DataTriggerOfStyle" Height="300" Width="300">
        <Window.Resources>
            <local:LongToBoolConverter x:Key="LongToBool"/>
            <Style TargetType="TextBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self},Path=Text.Length,Converter={StaticResource LongToBool}}" Value="false">
                        <Setter Property="BorderBrush" Value="Red"/>
                        <Setter Property="BorderThickness" Value="1"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <StackPanel>
            <TextBox Margin="5"/>
            <TextBox Margin="5"/>
            <TextBox Margin="5"/>
        </StackPanel>
    </Window>
    View Code
    public class LongToBoolConverter : IValueConverter
        {
            #region IValueConverter 成员
    
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                int textLength = (int)value;
                return textLength>6?true:false;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
    
            #endregion
        }

    效果为图14:

    图14

       上面的代码中有个的地方是需要解释一下,绑定中有个的RelativeSource,RelativeSource 通过指定绑定源相对于绑定目标的位置,获取或设置绑定源。上面的意思其实就是绑定源的本身。上面还有个Converter,参数中的value已经是长度了,所以不需要直接转化为int型就可以了。

     5.5多数据条件触发的MultiDataTrigger

      和上面的MultiTrigger相比,MultiDataTrigger主要验证数据,MultiTrigger验证属性。 

    XAML
    <Window x:Class="Style.MultiDataTriggerOfStyle"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MultiDataTriggerOfStyle" Height="300" Width="300">
        <Window.Resources>
            <Style TargetType="ListBoxItem">
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding ID}" Width="60"/>
                                <TextBlock Text="{Binding Name}" Width="120"/>
                                <TextBlock Text="{Binding Age}" Width="60"/>
                            </StackPanel>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=ID}" Value="2"/>
                            <Condition Binding="{Binding Path=Name}" Value="Tom"/>
                        </MultiDataTrigger.Conditions>
                        <MultiDataTrigger.Setters>
                            <Setter Property="Background" Value="Orange"/>
                        </MultiDataTrigger.Setters>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <StackPanel>
            <ListBox x:Name="listBoxStudent" Margin="5"/>
        </StackPanel>
    </Window>
    cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    
    namespace Style
    {
        /// <summary>
        /// MultiDataTriggerOfStyle.xaml 的交互逻辑
        /// </summary>
        public partial class MultiDataTriggerOfStyle : Window
        {
            public MultiDataTriggerOfStyle()
            {
                InitializeComponent();
                this.listBoxStudent.ItemsSource = new List<Student> { new Student { ID = 1, Name = "Tim", Age = 30 }
                                                                    , new Student { ID = 2, Name = "Tom", Age = 30 }
                                                                    , new Student { ID = 3, Name = "lzp", Age = 30 }
                                                                    , new Student { ID = 4, Name = "haiziguo", Age = 30 }};
            }
        }
        public class Student
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }

    效果如图15:

    图15

    5.6事件触发的EventTrigger

       该触发器与其他触发器不大一样,他不是属性也不是数据触发Style改变的,而是由事件触发的;被触发后不是执行的Setter,而是执行的一段动画。关于动画不做说明,下面只给出实例。记录完动画的章节,再回来看看。下面的例子是鼠标移到Button控件和离开执行的动画。

    XAML
    <Window x:Class="Style.EventTriggerOfStyle"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="EventTriggerOfStyle" Height="300" Width="300">
        <Window.Resources>
            <Style TargetType="Button">
                <Style.Triggers>
                    <EventTrigger RoutedEvent="MouseEnter">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation To="150" Duration="0:0:0:2" Storyboard.TargetProperty="Width"/>
                                <DoubleAnimation To="150" Duration="0:0:0:2" Storyboard.TargetProperty="Height"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="MouseLeave">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation  Duration="0:0:0:2" Storyboard.TargetProperty="Width"/>
                                <DoubleAnimation  Duration="0:0:0:2" Storyboard.TargetProperty="Height"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Style.Triggers>
            </Style>
        </Window.Resources>
        <Window.Triggers>
            <EventTrigger RoutedEvent="FrameworkElement.Loaded"/>
        </Window.Triggers>
        <Canvas>
            <Button Width="40" Height="40" Content="OK"/>
        </Canvas>
    </Window>

     六、总结

      本篇记录主要从DataTemplate和ControlTemplate入手,通过一些小例子来说明了他们的用途。注意区分其使用场合,前者只要是控制数据的显示方式,后者是控制控件的已有形状的改变。除此之外,还介绍了Style,由于其概念简单性,没有做过多的解释,只是给出了几个例子,等用到的时间再进行查阅。不足的地方是:关于ContentPresenter与DataTemplate以及ControlTemplate之间的关系不是太理解,所以本文少了一部分《寻找失落的控件》,如果有比较好的文章或者是比较好的资料帮助理解的,请留言,将不胜感激!本文是读书笔记,里面难免有理解不对的地方,欢迎讨论!最后祝大家节日愉快!下一篇:《深入浅出WPF》笔记——绘图与动画 。 

  • 相关阅读:
    Android游戏开发22:Android动画的实现J2me游戏类库用于Android开发
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第三部分,完整代码)
    使用OGR创建dxf格式矢量数据
    mysql 数据库引擎 MyISAM InnoDB 大比拼 区别
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第二部分)
    mysql 更改数据库引擎
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第一部分)
    android 数字键盘使用
    MySQL Innodb数据库性能实践
    eclipse : Error while performing database login with the driver null
  • 原文地址:https://www.cnblogs.com/lzhp/p/2705594.html
Copyright © 2011-2022 走看看