当前位置:   article > 正文

WPF 深入浅出 模板(DataTemplate 数据外衣、ControlTemplate 控件外衣、ItemsPanelTemplate 项布局

itemspaneltemplate

一、模板内函

模板就是“具有一定规格的样板”,有了模板,就可以依据它制造出很多一样的实例。

模板分为三大类:

DataTemplate 数据外衣

ControlTemplate 控件外衣

ItemsPanelTemplate 项布局(如:ListBox的item)


<Application.Resources>

<Style>

<Setter Property="Template">

<Setter.Value>

<ControlTemplate></ControlTemplate>

</Setter.Value>

</Setter>

</Style>

<DataTemplate></DataTemplate>

</Application.Resources>

二、DataTemplate 数据外衣(使用数据驱动)

效果:

代码:

  1. public class Car
  2. {
  3. public string Automake { get; set; }
  4. public string Name { get; set; }
  5. public string Year { get; set; }
  6. public string TopSpeed { get; set; }
  7. }

  1. //厂商名称转换成Logo图片路径
  2. public class AutomakerTologoPathConverter:IValueConverter
  3. {
  4. public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  5. {
  6. string uriStr = string.Format(@"/Resources/Images/{0}.jpg", (string)value);
  7. return new BitmapImage(new Uri(uriStr, UriKind.Relative));
  8. }
  9. public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  10. {
  11. throw new NotImplementedException();
  12. }
  13. }

窗体代码:

  1. <Window x:Class="WpfApplication.Window15"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:local="clr-namespace:WpfApplication"
  5. Title="Window15" Height="400" Width="700">
  6. <Window.Resources>
  7. <local:AutomakerTologoPathConverter x:Key="n2p"/>
  8. <!--详细页外衣-->
  9. <DataTemplate x:Key="carDetailViewTemplate">
  10. <Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
  11. <StackPanel Margin="5">
  12. <Image Width="400" Height="250"
  13. Source="{Binding Automake,Converter={StaticResource n2p}}"/>
  14. <StackPanel Orientation="Horizontal" Margin="5,0">
  15. <TextBlock Text="Name:" FontWeight="Bold" FontSize="20"/>
  16. <TextBlock Text="{Binding Name}" FontSize="20" Margin="5,0"/>
  17. </StackPanel>
  18. <StackPanel Orientation="Horizontal" Margin="5,0">
  19. <TextBlock Text="Automake:" FontWeight="Bold"/>
  20. <TextBlock Text="{Binding Automaker}" Margin="5,0"/>
  21. <TextBlock Text="Year:" FontWeight="Bold" />
  22. <TextBlock Text="{Binding Year}" Margin="5,0"/>
  23. <TextBlock Text="TopSpeed:" FontWeight="Bold" />
  24. <TextBlock Text="{Binding TopSeed}" Margin="5,0"/>
  25. </StackPanel>
  26. </StackPanel>
  27. </Border>
  28. </DataTemplate>
  29. <!--列表外衣-->
  30.  <DataTemplate x:Key="carListItemViewTemplate">
  31. <Grid Margin="2">
  32. <StackPanel Orientation="Horizontal">
  33. <Image Source="{Binding Automake, Converter={StaticResource n2p}}" Grid.RowSpan="3" Width="64" Height="64"/>
  34. <StackPanel Margin="5,0">
  35. <TextBlock Text="{Binding Name}" FontSize="16" FontWeight="Bold"/>
  36. <TextBlock Text="{Binding Year}" FontSize="14"/>
  37. </StackPanel>
  38. </StackPanel>
  39. </Grid>
  40. </DataTemplate>
  41. </Window.Resources>
  42. <!--窗体内容-->
  43. <StackPanel Orientation="Horizontal" Margin="5">
  44. <UserControl ContentTemplate="{StaticResource carDetailViewTemplate}"
  45. Content="{Binding SelectedItem,ElementName=listboxCars}"/>
  46. <ListBox x:Name="listboxCars" Width="180" Margin="5,0"
  47. ItemTemplate="{StaticResource carListItemViewTemplate}"/>
  48. </StackPanel>
  49. </Window>

ContentTemplate="{StaticResource carDetailViewTemplate}"   给用户控件添加外衣

ItemTemplate="{StaticResource carListItemViewTemplate}"     给ListBox每个Item项添加外衣



  1. public partial class Window15 : Window
  2. {
  3. public Window15()
  4. {
  5. InitializeComponent();
  6. InitialCarList();
  7. }
  8. private void InitialCarList()
  9. {
  10. List<Car> carList = new List<Car>()
  11. {
  12. new Car(){Automake="4",Name="name1",Year="1999",TopSpeed="300"},
  13. new Car(){Automake="5",Name="name2",Year="1990",TopSpeed="150"},
  14. new Car(){Automake="4",Name="name3",Year="1991",TopSpeed="350"},
  15. new Car(){Automake="5",Name="name4",Year="1995",TopSpeed="400"},
  16. };
  17. listboxCars.ItemsSource = carList;
  18. }
  19. }


三、ControlTemplate 控件外衣

    <Application.Resources>
        <Style x:Key="键名" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
              <!---属性简单直接value,属性复杂就Setter.Value->
                 <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                 <Setter Property="Template">
                                    <Setter.Value>
                                                         <ControlTemplate TargetType="{x:Type TextBox}">
                                                                   外衣
                                                                  <ControlTemplate.Triggers>
                                                                        <Trigger>
                                                                           触发器
                                                                        </Trigger>
                                                                </ControlTemplate.Triggers>
                                                       </ControlTemplate>
                                     </Setter.Value>
                </Setter>
        </Style>
       <Application.Resources>


实例:输入文本框,边圆角

第一步:控件模板

  1. <Application.Resources>
  2. <LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" MappingMode="Absolute" StartPoint="0,0">
  3. <GradientStop Color="#ABADB3" Offset="0.05"/>
  4. <GradientStop Color="#E2E3EA" Offset="0.07"/>
  5. <GradientStop Color="#E3E9EF" Offset="1"/>
  6. </LinearGradientBrush>
  7. <Style x:Key="RoundCornerTextBoxStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
  8. <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  9. <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
  10. <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
  11. <Setter Property="BorderThickness" Value="1"/>
  12. <Setter Property="Padding" Value="1"/>
  13. <Setter Property="AllowDrop" Value="true"/>
  14. <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
  15. <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
  16. <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
  17. <Setter Property="Template">
  18. <Setter.Value>
  19. <ControlTemplate TargetType="{x:Type TextBox}">
  20. <Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5">
  21. <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
  22. </Border>
  23. <ControlTemplate.Triggers>
  24. <Trigger Property="IsEnabled" Value="false">
  25. <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
  26. <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
  27. </Trigger>
  28. </ControlTemplate.Triggers>
  29. </ControlTemplate>
  30. </Setter.Value>
  31. </Setter>
  32. </Style>
  33. <!-- 应该在此定义应用程序级的资源。-->
  34. </Application.Resources>

注意:TemplateBinding 将自己的属性关联到目标控件的某个属性上。


第二步:样式绑定模板

<TextBox Style="{DynamicResource RoundCornerTextBoxStyle}"/>


四、ItemsControl的PanelTemplate

      控制 ItemControl条目容器

        <ListBox>


            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>    条目会包装放到一个水平排列的StackPanel中
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>


            <!--条目-->
            <TextBlock Text="A"/>
            <TextBlock Text="B"/>
            <TextBlock Text="C"/>
            <TextBlock Text="D"/>


        </ListBox>



五、DataTemplate 与 ControlTemplate 的关系与应用

决定控件外观的是 ControlTemplate,  是控件                  Template 属性的值
决定数据外观的是 DataTemplate    ,   是控件   ContentTemplate 属性的值





       ContentPresenter(内容content,内容位置,内容模板 contentTemplate) 控件是ControlTemplate控件树的一个结点。
       DataTemplate 控件树是 ControlTemplae控件树的一颗子树。



1、所有目标样式

<Window>
  <Style TargetType="{x:Type TextBox}">
    <Setter Property="Template">
         <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                控件模板
            </ControlTemplate>
        </Setter.Value>
    </Setter>
  </Style>

  <StackPanel>
  <TextBox/>
  <TextBox Style="{x:null}" text="不应用样式"/>
  </StackPanel>
</Window>


2、设置 DataTemplate 的 DataType 属性,可以把 DataTemplate 应用在那种数据类型上。

效果:


代码:

创建数据类型

  1. public class Unit
  2. {
  3. public int Price { get; set; }
  4. public string Year { get; set; }
  5. }

数据类型模板、数据类型源

<Window x:Class="WpfApplication.Window17"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"

        Title="Window17" 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}" Margin="5,0"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
        <!--数据类型 (源)-->
        <c:ArrayList x:Key="ds">
            <local:Unit Year="2001年" Price="100"/>
            <local:Unit Year="2002年" Price="150"/>
            <local:Unit Year="2003年" Price="180"/>
        </c:ArrayList>
    </Window.Resources>
    <StackPanel>
        <!--绑定数据类型源-->
        <ListBox ItemsSource="{StaticResource ds}"/>
        <ComboBox ItemsSource="{StaticResource ds}"/>
    </StackPanel>
</Window>



3、XmlDataProvider 做为数据源

<Window x:Class="WpfApplication.Window17"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib">
    <Window.Resources>
        <!--数据类型 (模板)-->
        <DataTemplate DataType="Unit">
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <Grid>
                        <Rectangle Stroke="Yellow" Fill="Orange" Width="{Binding XPath=@Price}"/>
                        <TextBlock Text="{Binding XPath=@Year}"/>
                    </Grid>
                    <TextBlock Text="{Binding XPath=@Price}" Margin="5,0"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
        <XmlDataProvider x:Key="ds" XPath="Units/Unit">
            <x:XData>
                <Units xmlns="">
                    <Unit Year="2001" Price="150"/>
                    <Unit Year="2002" Price="180"/>
                    <Unit Year="2003" Price="200"/>
                </Units>
            </x:XData>
        </XmlDataProvider>
        
    </Window.Resources>
    <StackPanel>
        <!--绑定数据类型源-->
        <ListBox ItemsSource="{Binding Source={StaticResource ds}}"/>
        <ComboBox ItemsSource="{Binding Source={StaticResource ds}}"/>
    </StackPanel>
</Window>


4、TreeView  显示多层级,不同类型的数据。因为数据类型不同,我们需要每种数据类型设置一种模板。

       使用层级数据模板 HierarchicalDataTemplate


xml数据

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <Data xmlns="">
  3. <Grade Name="一年级">
  4. <Class Name="甲班">
  5. <Group Name="A组"/>
  6. <Group Name="B组"/>
  7. </Class>
  8. </Grade>
  9. </Data>

  1. <Window x:Class="AutomaticConfigurationAPP.Window3"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="Window3" Height="300" Width="300">
  5. <Window.Resources>
  6. <!--Source数据源 XPath数据源路径-->
  7. <XmlDataProvider x:Key="ds" Source="/Resources/Xml/Data.xml" XPath="Data/Grade"/>
  8. <!--年级模板-->
  9. <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">
  10. <TextBlock Text="{Binding XPath=@Name}" />
  11. </HierarchicalDataTemplate>
  12. <!--班级模板-->
  13. <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
  14. <RadioButton Content="{Binding XPath=@Name}" GroupName="gn"/>
  15. </HierarchicalDataTemplate>
  16. <!--小组模板-->
  17. <HierarchicalDataTemplate DataType="Group">
  18. <CheckBox Content="{Binding XPath=@Name}"/>
  19. </HierarchicalDataTemplate>
  20. </Window.Resources>
  21. <Grid>
  22. <TreeView Margin="5" ItemsSource="{Binding Source={StaticResource ds}}"/>
  23. </Grid>
  24. </Window>


5、同一种数据类型的嵌套结构。

      只设计一个 HierarchicalDataTemplate ,会自动产生迭代效果。


效果:


  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <Data xmlns="">
  3. <Operation Name="文件" Gesture="F">
  4. <Operation Name="新建" Gesture="N">
  5. <Operation Name="项目" Gesture="Control + P"/>
  6. <Operation Name="网站" Gesture="Control + W"/>
  7. </Operation>
  8. </Operation>
  9. </Data>


  1. <Window x:Class="AutomaticConfigurationAPP.Window4"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="Window4" Height="300" Width="300">
  5. <Window.Resources>
  6. <!--Source数据源 XPath数据路径-->
  7. <XmlDataProvider x:Key="ds" Source="/Resources/Xml/Data2.xml" XPath="Data/Operation"/>
  8. <!--数据模板-->
  9. <HierarchicalDataTemplate DataType="Operation" ItemsSource="{Binding XPath=Operation}">
  10. <StackPanel Orientation="Horizontal">
  11. <TextBlock Text="{Binding XPath=@Name}" Margin="10,0"/>
  12. <TextBlock Text="{Binding XPath=@Gesture}"/>
  13. </StackPanel>
  14. </HierarchicalDataTemplate>
  15. </Window.Resources>
  16. <StackPanel MenuItem.Click="StackPanel_Click">
  17. <Menu ItemsSource="{Binding Source={StaticResource ds}}"/>
  18. </StackPanel>
  19. </Window>


  1. private void StackPanel_Click(object sender, RoutedEventArgs e)
  2. {
  3. MenuItem mi = e.OriginalSource as MenuItem;
  4. //HierarchicalDataTemplate 作用的目标是MenuItem.Header
  5. XmlElement xe = mi.Header as XmlElement;
  6. MessageBox.Show(xe.Attributes["Name"].Value);
  7. }


六、从外部访问 Template (模板)的控件、获取它的属性值

        DataTemplate 和 ControlTemplate 两个类均派生自 FrameWorkTemplate类。这个类有个 FindName方法 供我们查询内部控件。

        ControlTemplate 对象: 访问其目标控件 Template . FindName就能拿到。

        DataTemplate 对象:     直接使用低层数据(如果想获得控件长度、宽度 Template . FindName)。


1、获得ControlTemplate 中的控件。

效果:



<Window x:Class="AutomaticConfigurationAPP.Window5"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window5" Height="300" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="cTmp">
            <StackPanel Background="Orange">
               <TextBox x:Name="textbox1" Margin="6"/>
                <TextBox x:Name="textbox2" Margin="6,0"/>
                <TextBox x:Name="textbox3" Margin="6"/>
            </StackPanel>
        </ControlTemplate>
    </Window.Resources>
    <StackPanel Background="Yellow">
        <UserControl x:Name="uc" Template="{StaticResource cTmp}" Margin="5"/>
        <Button Content="FindName" Click="Button_Click"/>
    </StackPanel>
</Window>

事件

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //Template.FindName
            TextBox tb= uc.Template.FindName("textbox1", this.uc) as TextBox;

            tb.Text = "textbox1";
            StackPanel sp = tb.Parent as StackPanel;
            (sp.Children[1] as TextBox).Text = "textbox2";
            (sp.Children[2] as TextBox).Text = "textbox3";
        }


2、获得DataTemplate 中的控件。

     如果获得与用户界面相关的数据(比如控件的宽度、高度)ContentTemplate.FindName("")。

     如果获得与业务相关的数据,直接访问底层(WPF采用数据驱动UI逻辑)Content

效果:

  1. public class Student
  2. {
  3. public int Id { get; set; }
  4. public string Name { get; set; }
  5. public string Skill { get; set; }
  6. public bool HasJob { get; set; }
  7. }

XAML

<Window x:Class="AutomaticConfigurationAPP.Window6"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:AutomaticConfigurationAPP"
        Title="Window6" Height="300" Width="300">
    <Window.Resources>
        <local:Student x:Key="stu" Id="1" Name="姓名" Skill="wpf" HasJob="True"/>
        
        <DataTemplate x:Key="stuDT">

            <Border BorderBrush="Orange" BorderThickness="2" CornerRadius="5">
                <StackPanel>
                    <TextBlock Text="{Binding Id}" Margin="5"/>
                    <TextBlock x:Name="textblockname" Text="{Binding Name}" Margin="5"/>
                    <TextBlock Text="{Binding Skill}" Margin="5"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <StackPanel>
        <ContentPresenter x:Name="cp" 
                          Content="{StaticResource stu}" 
                          ContentTemplate="{StaticResource stuDT}"

                          Margin="5"/>
        <!--Content="{StaticResource 内容数据源}" ContentTemplate="{StaticResource 内容模板}"-->
        <Button Content="Find" Margin="5,0" Click="Button_Click"/>
    </StackPanel>
</Window>


C#

           //内容模板查找控件
           TextBlock tb= this.cp.ContentTemplate.FindName("textblockname", this.cp) as TextBlock;
           MessageBox.Show(tb.Text);


           //直接使用底层数据
           Student stu = this.cp.Content as Student;
           MessageBox.Show(stu.Name);



实例:访问业务逻辑数据、访问界面逻辑数据

界面:



XAML


<Window x:Class="AutomaticConfigurationAPP.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        xmlns:local="clr-namespace:AutomaticConfigurationAPP"

        Title="Window2" Height="300" Width="300">
    <Window.Resources>
        <c:ArrayList x:Key="stuList">
            <local:Student Id="1" Name="a" Skill="wpf" HasJob="True"/>
            <local:Student Id="2" Name="b" Skill="MVC" HasJob="True"/>
            <local:Student Id="3" Name="c" Skill="c#" HasJob="True"/>
        </c:ArrayList>
        <DataTemplate x:Key="nameDT">
            <TextBox x:Name="textboxname" Text="{Binding Name}" GotFocus="textboxname_GotFocus"/>
        </DataTemplate>
        <DataTemplate x:Key="skillDT">
            <TextBox x:Name="textboxskill" Text="{Binding Skill}"/>
        </DataTemplate>
        <DataTemplate x:Key="hasjobDT">
            <CheckBox x:Name="checkboxJob" IsChecked="{Binding HasJob}"/>
        </DataTemplate>
    </Window.Resources>
    <Grid Margin="5">
        <ListView x:Name="listviewStudent" ItemsSource="{StaticResource stuList}">
            <ListView.View>


                <!--ListView的View属性是GridView-->
                <GridView>
                    <GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}"/>
                    <!--CellTemplate是TextBox-->
                    <GridViewColumn Header="姓名" CellTemplate="{StaticResource nameDT}"/>
                    <GridViewColumn Header="技能" CellTemplate="{StaticResource skillDT}"/>
                    <GridViewColumn Header="已工作" CellTemplate="{StaticResource hasjobDT}"/>
                </GridView>
                
            </ListView.View>
        </ListView>


    </Grid>
</Window>


c#

        private void textboxname_GotFocus(object sender, RoutedEventArgs e)
        {
            //访问业务逻辑数据
            TextBox tb = e.OriginalSource as TextBox;//获得事件的源头(TextBox)
            //沿UI元素树上溯到DataTemplate的目标控件(ContentPresenter),并获取它内容,它内容一定是个Student
            ContentPresenter cp = tb.TemplatedParent as ContentPresenter;
            Student stu = cp.Content as Student;//一行
            //MessageBox.Show(stu.HasJob.ToString());
            this.listviewStudent.SelectedItem = stu;


            //访问界面逻辑数据
            //查找包含的ListViewItem
            ListViewItem lvi = this.listviewStudent.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;
            CheckBox chb = this.FindVisualChild<CheckBox>(lvi);
            MessageBox.Show(chb.Name);


        }


        private ChildType FindVisualChild<ChildType>(DependencyObject obj)
            where ChildType:DependencyObject
        {
            //可视化对象包含的子集个数
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                //返回指定父可视对象中位于指定集合索引位置的子可视对象
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is ChildType)
                {
                    return child as ChildType;
                }
                else
                {
                    ChildType childofChild = FindVisualChild<ChildType>(child);
                    if (childofChild != null)
                        return childofChild;
                }
            }
            return null;
        }


七、Style 样式

Style样式包含两种元素:

Setter类  设置控件静态的外观。

Trigger类 设置控件行为的风格。


实例一:模板绑定Padding属性的值,并使用属性值在ContentPresenter 元素周围创建外边距。



  1. <Button Margin="5" Padding="5" Background="Black" Template="{Binding Source={StaticResource ButtonTemplate}}">
  2. 控件模板
  3. </Button>

  1. <Window.Resources>
  2. <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
  3. <Border Name="borderName"
  4. BorderBrush="Orange"
  5. BorderThickness="3"
  6. CornerRadius="2"
  7. Background="Red"
  8. TextBlock.Foreground="White">
  9. <!-- ContentPresenter 就是負責將Content屬性顯示出來 -->
  10. <!--模板绑定:模板从 应用模板 中获取值 Margin="{TemplateBinding Padding}"-->
  11. <ContentPresenter
  12. RecognizesAccessKey="True"
  13. Margin="{TemplateBinding Padding}">
  14. </ContentPresenter>
  15. </Border>
  16. <ControlTemplate.Triggers>
  17. <Trigger Property="IsMouseOver" Value="True">
  18. <Setter TargetName="borderName" Property="Background" Value="DarkRed"/>
  19. </Trigger>
  20. <Trigger Property="IsPressed" Value="True">
  21. <Setter TargetName="borderName" Property="Background" Value="IndianRed"/>
  22. <Setter TargetName="borderName" Property="BorderBrush" Value="DarkKhaki"/>
  23. </Trigger>
  24. </ControlTemplate.Triggers>
  25. </ControlTemplate>
  26. </Window.Resources>


实例二:动画按钮

    <Window.Resources>
        <ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
            <Border BorderBrush="Orange" 
                    BorderThickness="3" 
                    CornerRadius="2"
                    Background="Red" 
                    TextBlock.Foreground="White" 
                    Name="Border">
                <Grid>
                    <Rectangle Name="FocusCue" 
                               Visibility="Hidden" 
                               Stroke="Black"
                               StrokeThickness="1" 
                               StrokeDashArray="1 2"
                               SnapsToDevicePixels="True" >
                        
                    </Rectangle>
                    <ContentPresenter RecognizesAccessKey="True"
                                 Margin="{TemplateBinding Padding}">
                        
                    </ContentPresenter>
                </Grid>
            </Border>
            <ControlTemplate.Triggers>
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color"
                                            To="Blue" Duration="0:0:1" AutoReverse="True" RepeatBehavior="Forever"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" Duration="0:0:0.5"></ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>

                <Trigger Property="IsPressed" Value="True">
                    <Setter TargetName="Border" Property="Background" Value="IndianRed" />
                    <Setter TargetName="Border" Property="BorderBrush" Value="DarkKhaki" />
                </Trigger>
                <Trigger Property="IsKeyboardFocused" Value="True">
                    <Setter TargetName="FocusCue" Property="Visibility" Value="Visible" />
                </Trigger>

            </ControlTemplate.Triggers>
        </ControlTemplate>

    </Window.Resources>


实例三:修改LIstBox样式(嵌套模板)。


步骤:

1、ItemsPresenter 外观(ListBox)

2、ContentPresenter 外观(ListBoxItem)

3、ScrollBar外观



  1. <Window x:Class="AutomaticConfigurationAPP.Window1"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="Window1" Height="300" Width="300">
  5. <Window.Resources>
  6. <!--单色画刷-->
  7. <SolidColorBrush x:Key="StandardBorderBrush" Color="#888" />
  8. <SolidColorBrush x:Key="HoverBorderBrush" Color="#DDD" />
  9. <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="Gray" />
  10. <SolidColorBrush x:Key="SelectedForegroundBrush" Color="White" />
  11. <LinearGradientBrush x:Key="ListBoxBackgroundBrush" StartPoint="0,0" EndPoint="1,0.001">
  12. <GradientBrush.GradientStops>
  13. <GradientStopCollection>
  14. <GradientStop Color="White" Offset="0.0" />
  15. <GradientStop Color="White" Offset="0.6" />
  16. <GradientStop Color="#DDDDDD" Offset="1.2"/>
  17. </GradientStopCollection>
  18. </GradientBrush.GradientStops>
  19. </LinearGradientBrush>
  20. <LinearGradientBrush x:Key="StandardBrush" StartPoint="0,0" EndPoint="0,1">
  21. <GradientBrush.GradientStops>
  22. <GradientStopCollection>
  23. <GradientStop Color="#FFF" Offset="0.0"/>
  24. <GradientStop Color="#CCC" Offset="1.0"/>
  25. </GradientStopCollection>
  26. </GradientBrush.GradientStops>
  27. </LinearGradientBrush>
  28. <SolidColorBrush x:Key="GlyphBrush" Color="#444" />
  29. <LinearGradientBrush x:Key="PressedBrush" StartPoint="0,0" EndPoint="0,1">
  30. <GradientBrush.GradientStops>
  31. <GradientStopCollection>
  32. <GradientStop Color="#BBB" Offset="0.0"/>
  33. <GradientStop Color="#EEE" Offset="0.1"/>
  34. <GradientStop Color="#EEE" Offset="0.9"/>
  35. <GradientStop Color="#FFF" Offset="1.0"/>
  36. </GradientStopCollection>
  37. </GradientBrush.GradientStops>
  38. </LinearGradientBrush>
  39. <!--滚动条按钮为圆圈-->
  40. <Style x:Key="ScrollBarLineButtonStyle" TargetType="{x:Type RepeatButton}">
  41. <Setter Property="Focusable" Value="False"/>
  42. <Setter Property="Template">
  43. <Setter.Value>
  44. <ControlTemplate TargetType="{x:Type RepeatButton}">
  45. <Grid Margin="1">
  46. <Ellipse Name="Border" StrokeThickness="1" Stroke="{StaticResource StandardBorderBrush}"
  47. Fill="{StaticResource StandardBrush}"></Ellipse>
  48. <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
  49. </Grid>
  50. <ControlTemplate.Triggers>
  51. <Trigger Property="IsPressed" Value="true">
  52. <Setter TargetName="Border" Property="Fill" Value="{StaticResource PressedBrush}" />
  53. </Trigger>
  54. </ControlTemplate.Triggers>
  55. </ControlTemplate>
  56. </Setter.Value>
  57. </Setter>
  58. </Style>
  59. <!--滚动条Thumb上的RepeatButton对象,背景为透明-->
  60. <Style x:Key="ScrollBarPageButtonStyle" TargetType="{x:Type RepeatButton}">
  61. <Setter Property="IsTabStop" Value="False"/>
  62. <Setter Property="Focusable" Value="False"/>
  63. <Setter Property="Template">
  64. <Setter.Value>
  65. <ControlTemplate TargetType="{x:Type RepeatButton}">
  66. <Border Background="Transparent" />
  67. </ControlTemplate>
  68. </Setter.Value>
  69. </Setter>
  70. </Style>
  71. <!--滚动条Thumb形状为椭圆-->
  72. <Style x:Key="ScrollBarThumbStyle" TargetType="{x:Type Thumb}">
  73. <Setter Property="IsTabStop" Value="False"/>
  74. <Setter Property="Focusable" Value="False"/>
  75. <Setter Property="Margin" Value="1,0,1,0" />
  76. <Setter Property="Background" Value="{StaticResource StandardBrush}" />
  77. <Setter Property="BorderBrush" Value="{StaticResource StandardBorderBrush}" />
  78. <Setter Property="Template">
  79. <Setter.Value>
  80. <ControlTemplate TargetType="{x:Type Thumb}">
  81. <Ellipse Stroke="{StaticResource StandardBorderBrush}"
  82. Fill="{StaticResource StandardBrush}"></Ellipse>
  83. </ControlTemplate>
  84. </Setter.Value>
  85. </Setter>
  86. </Style>
  87. <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
  88. <Grid>
  89. <!--滚动条包含三行网格。顶部,低部放按钮。中间Track元素-->
  90. <Grid.RowDefinitions>
  91. <RowDefinition MaxHeight="18"/>
  92. <RowDefinition Height="*"/>
  93. <RowDefinition MaxHeight="18"/>
  94. </Grid.RowDefinitions>
  95. <RepeatButton
  96. Grid.Row="0"
  97. Height="18"
  98. Style="{StaticResource ScrollBarLineButtonStyle}"
  99. Command="ScrollBar.LineUpCommand" >
  100. <!--绘制向上箭头的Path对象(箭头使用,微语言路径)-->
  101. <Path
  102. Fill="{StaticResource GlyphBrush}"
  103. Data="M 0 4 L 8 4 L 4 0 Z">
  104. </Path>
  105. </RepeatButton>
  106. <!--Track名称必须是PART_Track,为了使ScrollBar能成功关联到它的代码-->
  107. <!--ViewportSize="0" 尺度更具内容变化-->
  108. <Track
  109. Name="PART_Track"
  110. Grid.Row="1"
  111. IsDirectionReversed="True"
  112. ViewportSize="0">
  113. <!--Track封装两个RepeatButton对象和Thumb元素-->
  114. <Track.DecreaseRepeatButton>
  115. <RepeatButton Command="ScrollBar.PageUpCommand" Style="{StaticResource ScrollBarPageButtonStyle}">
  116. </RepeatButton>
  117. </Track.DecreaseRepeatButton>
  118. <Track.Thumb>
  119. <Thumb Style="{StaticResource ScrollBarThumbStyle}">
  120. </Thumb>
  121. </Track.Thumb>
  122. <Track.IncreaseRepeatButton>
  123. <RepeatButton Command="ScrollBar.PageDownCommand" Style="{StaticResource ScrollBarPageButtonStyle}">
  124. </RepeatButton>
  125. </Track.IncreaseRepeatButton>
  126. </Track>
  127. <RepeatButton
  128. Grid.Row="3"
  129. Height="18"
  130. Style="{StaticResource ScrollBarLineButtonStyle}"
  131. Command="ScrollBar.LineDownCommand">
  132. <Path
  133. Fill="{StaticResource GlyphBrush}"
  134. Data="M 0 0 L 4 4 L 8 0 Z">
  135. </Path>
  136. </RepeatButton>
  137. </Grid>
  138. </ControlTemplate>
  139. <Style TargetType="{x:Type ScrollBar}">
  140. <Setter Property="SnapsToDevicePixels" Value="True"/>
  141. <Setter Property="OverridesDefaultStyle" Value="true"/>
  142. <Style.Triggers>
  143. <!--垂直滚动条模板-->
  144. <Trigger Property="Orientation" Value="Vertical">
  145. <Setter Property="Width" Value="18"/>
  146. <Setter Property="Height" Value="Auto" />
  147. <Setter Property="Template" Value="{StaticResource VerticalScrollBar}" />
  148. </Trigger>
  149. </Style.Triggers>
  150. </Style>
  151. <!-- ItemsPresenter 外观-->
  152. <Style TargetType="{x:Type ListBox}">
  153. <Setter Property="Template">
  154. <Setter.Value>
  155. <ControlTemplate TargetType="{x:Type ListBox}">
  156. <!--嵌套模板-->
  157. <Border
  158. Name="border"
  159. Background="{StaticResource ListBoxBackgroundBrush}"
  160. BorderBrush="{StaticResource StandardBorderBrush}"
  161. BorderThickness="1" CornerRadius="3"
  162. >
  163. <!--ScrollViewer 容纳所有列表项(ItemsPresenter)-->
  164. <ScrollViewer Focusable="False">
  165. <ItemsPresenter Margin="2"></ItemsPresenter>
  166. </ScrollViewer>
  167. </Border>
  168. </ControlTemplate>
  169. </Setter.Value>
  170. </Setter>
  171. </Style>
  172. <!-- ContentPresenter 外观-->
  173. <Style TargetType="{x:Type ListBoxItem}">
  174. <Setter Property="Template">
  175. <Setter.Value>
  176. <ControlTemplate TargetType="{x:Type ListBoxItem}">
  177. <Border
  178. Name="Border"
  179. BorderThickness="2"
  180. CornerRadius="3"
  181. Padding="1"
  182. SnapsToDevicePixels="True">
  183. <ContentPresenter></ContentPresenter>
  184. </Border>
  185. <ControlTemplate.Triggers>
  186. <EventTrigger RoutedEvent="ListBoxItem.MouseEnter">
  187. <EventTrigger.Actions>
  188. <BeginStoryboard>
  189. <Storyboard>
  190. <DoubleAnimation
  191. Storyboard.TargetProperty="FontSize"
  192. To="20"
  193. Duration="0:0:1">
  194. </DoubleAnimation>
  195. <!--字体1秒钟=20大小-->
  196. </Storyboard>
  197. </BeginStoryboard>
  198. </EventTrigger.Actions>
  199. </EventTrigger>
  200. <EventTrigger RoutedEvent="ListBoxItem.MouseLeave">
  201. <EventTrigger.Actions>
  202. <BeginStoryboard>
  203. <Storyboard>
  204. <DoubleAnimation
  205. Storyboard.TargetProperty="FontSize"
  206. BeginTime="0:0:0.5"
  207. Duration="0:0:0.2">
  208. <!--字体延迟0.5秒,0.2秒缩小-->
  209. </DoubleAnimation>
  210. </Storyboard>
  211. </BeginStoryboard>
  212. </EventTrigger.Actions>
  213. </EventTrigger>
  214. <Trigger Property="IsMouseOver" Value="True">
  215. <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource HoverBorderBrush}"/>
  216. </Trigger>
  217. <Trigger Property="IsSelected" Value="True">
  218. <Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/>
  219. <Setter TargetName="Border" Property="TextBlock.Foreground" Value="{StaticResource SelectedForegroundBrush}"/>
  220. </Trigger>
  221. </ControlTemplate.Triggers>
  222. </ControlTemplate>
  223. </Setter.Value>
  224. </Setter>
  225. </Style>
  226. </Window.Resources>
  227. <Grid>
  228. <ListBox Height="100">
  229. <ListBoxItem Content="1" />
  230. <ListBoxItem Content="2" />
  231. <ListBoxItem Content="3" />
  232. <ListBoxItem Content="4" />
  233. <ListBoxItem Content="5" />
  234. <ListBoxItem Content="6" />
  235. <ListBoxItem Content="7" />
  236. <ListBoxItem Content="8" />
  237. </ListBox>
  238. </Grid>
  239. </Window>


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/928556
推荐阅读
相关标签
  

闽ICP备14008679号