zoukankan      html  css  js  c++  java
  • WPF 详解模板

    在WPF中有三大模板ControlTemplate,ItemsPanelTemplate,DataTemplate.其中ControlTemplate和ItemsPanelTemplate是控件模板,DataTemplate是数据模板,他们都派生自FrameworkTemplate抽象类。

    1、ControlTemplate

    ControlTemplate:控件模板主要有两个重要属性:VisualTree内容属性和Triggers触发器。所谓VisualTree(视觉树),就是呈现我们所画的控件。Triggers可以对我们的视觉树上的元素进行一些变化。一般用于单内容控件。

    画一个按钮模板来举例说明:

    <Style TargetType="Button">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Grid>
                                <Ellipse Width="100" Height="100">
                                    <Ellipse.Fill>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                            <GradientStop Offset="0" Color="blue"/>
                                            <GradientStop Offset="1" Color="LightBlue"/>
                                        </LinearGradientBrush>
                                    </Ellipse.Fill>
                                </Ellipse>
                                <Ellipse Width="80" Height="80">
                                    <Ellipse.Fill>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                            <GradientStop Offset="0" Color="White"/>
                                            <GradientStop Offset="1" Color="Transparent"/>
                                        </LinearGradientBrush>
                                    </Ellipse.Fill>
                                </Ellipse>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

    <Button Content="Hello WPF"/>

    结果:image

    ControlTemplate之子 ContentControl和ContentPresenter

    我们在ControlTemplate中画了两个椭圆,应用于所有的Button按钮,但我们Button中有Content属性(内容为Hello WPF),却没有显示出来。因为这里用ControlTemplate重写了Button的样式,所以我们也要在ControlTemplate中增加ContentControl。通过ContentControl中的Content来绑定父容器的Content属性。

    代码

    这下内容出来了image

    我们来看一下,ContentControl继承于Control的,用MSDN的话是:表示包含单项内容的控件、ContentControl 可以包含任何类型的公共语言运行库对象。如下ContentControl类图。

    image

    为了提高性能,我们可以用一个ControlPresenter来代替ContentControl,效果还是一样,那他们有什么区别呢?

    来看下ControlPresenter这个类,它继承于FreameworkElement,如下图:

    image

    ControlPresenter 通常叫做内容占位符。所以我们可以看到

    <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>来代替<ContentControl VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}"/> 这里少了Content绑定父容器,因为ControlPresenter有个隐式的Content="{TemplateBinding Content}",也就是你可以写也可以不写它。

    从他们的基类可以看出,ContentControl比ContentPresenter大多了。其实ControlPresenter是一个原始的构建块,而ContentControl是一个带控件模板的成熟控件(里面包含ControlPresenter)。

    所以我们一般用ControlPresenter。

    ControlTemplate的VisualTree我们讲过了,下面看下他的trigger如何运用。

    我们在原来的代码中增加

    <ControlTemplate.Triggers>
                 <Trigger Property="IsMouseOver" Value="true">
                       <Setter TargetName="ellipse1" Property="Fill" Value="Red"/>
                 </Trigger>
     </ControlTemplate.Triggers>

    当我们把鼠标移上去的时候就会变成如下图所示:

    image

    发挥我们的想象力,我们可以根据ControlTemplate做更多的特效。如下

    <Style TargetType="CheckBox">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="CheckBox">
                            <DockPanel>
                                <ContentPresenter DockPanel.Dock="Left" VerticalAlignment="Center" />
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="30"/>
                                        <ColumnDefinition Width="30"/>
                                    </Grid.ColumnDefinitions>
                                    <Rectangle Grid.Column="0" Grid.ColumnSpan="2" Fill="Gray"/>
                                    <TextBlock x:Name="txtBox"  Foreground="White" />
                                </Grid>
                            </DockPanel>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter TargetName="txtBox" Property="Grid.Column" Value="1"/>
                                    <Setter TargetName="txtBox" Property="Text" Value="On"/>
                                    <Setter TargetName="txtBox" Property="Background" Value="LightBlue"/>
                                </Trigger>
                                <Trigger Property="IsChecked" Value="{x:Null}">
                                    <Setter TargetName="txtBox" Property="Grid.Column" Value="0"/>
                                </Trigger>
                                <Trigger Property="IsChecked" Value="false">
                                    <Setter TargetName="txtBox" Property="Grid.Column" Value="0"/>
                                    <Setter TargetName="txtBox" Property="Text" Value="OFF"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    <Grid>
            <CheckBox Width="100" Height="30" Content="Click Me"/>
     </Grid>

    效果图:点击之前image点击之后image

    2、ItemsPanelTemplate

    ItemsPanelTemplate在MSDN的解释是:ItemsPanelTemplate 指定用于项的布局的面板。 GroupStyle 具有一个类型为 ItemsPanelTemplate 的 Panel 属性。 ItemsControl 类型具有一个类型为ItemsPanelTemplate 的 ItemsPanel 属性。

    我们先讲ItemTemplate。它一般用在多个内容控件的模板。比如ListBox。

    如下看ListBox应用ItemTemplate:

    在xaml中

    <Style TargetType="ListBox">
                <Setter Property="ItemTemplate">
                    <Setter.Value>
                        <DataTemplate>
                             <Image Source="{Binding UriSource}" Width="100" Height="100"/>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

      <ListBox x:Name="listBox" />

    在后台代码我们给它一些图片来填充这个ListBox.

    代码

    image每一张图片就是一个Item。

    我们如果想让图片以横向显示。一开始我以为用StackPanel的Orientation=”Horiziontal”,发现犯了个错误。这样设置是现在把Items中某一个item中的内容水平显示啊。这时就要用到ItemsPanelTemplate这个模板了。我们在ListBox的样式中增加如下红色区域的代码:

     <Style TargetType="ListBox">
                <Setter Property="ItemTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Image Source="{Binding UriSource}" Width="100" Height="100"/>
                                <TextBlock Text="qq" Background="Red"/>
                            </StackPanel>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
               

    <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel /> </ItemsPanelTemplate> </Setter.Value> </Setter>

            </Style>


    这里我在DataTemplate中加了StackPanel 为了说明加在这里的效果只是区分:Items整体横向和Item中内容的区别。

    image

    现在我们要想让布局可以随着窗体宽度变化,我们只要把ItemsPanelTemplate中的StackPanel 改成WrapPanel,并且设置ListBox的ScrollViewer.HorizontalScrollBarVisibility="Disabled",这样才可以看到效果。

    image

    ControlTemplate之 ItemsPresenter和ContentPresenter

    我们先构造一个TreeView

    xaml中:

    在开始加个Loaded="UserControl_Loaded"

    <Grid>
            <TreeView x:Name="treeview" />
    </Grid>

    后台代码中:

    代码

    没有任何样式的TreeView

    image

    下面我们如何运用ItemsPresenter和ContentPresenter来添加样式。来实现下面这幅图的效果

    image
    在TreeView中ItemsPresenter和ContentPresenter是什么关系:ContentPresenter是用来显示TreeView中Item的内容 。ItemsPresenter是用来显示它的子项(Item的子项,也就是说child’s Items)。

    样式代码

    看红色代码的部分,这里ContentPresenter显示了父容器的Header的内容,比如GrandFather,Father,Son.而ItemsPresenter则是否让他显示其子元素。比如GrandFather的子元素为Father,没有设置<ItemsPresenter Grid.Row="1"/> 的话。子元素Father是不会显示的。

    这里为了突出层次化,运用了ItemsPanelTemplate。最后我们在资源里引用这个样式。

    代码

    3、DataTemplate和HierarchicalDataTemplate

    DataTemplate就是显示绑定数据对象的模板。
    HierarchicalDataTemplate继承于DataTemplate,它专门对TreeViewItemMenuItem的一些数据对象的绑定。

    想了解下DataTemplate和HierarchicalDataTemplate,就看以上的例子吧。他们中只要有控件的绑定都会用到。想了解的更深一步,请看下南柯之石的这篇文章。


    作者:dingli
    出处:http://www.cnblogs.com/dingli/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Java对象的生命周期与作用域的讨论(转)
    [置顶] Oracle学习路线与方法
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
  • 原文地址:https://www.cnblogs.com/dingli/p/2112150.html
Copyright © 2011-2022 走看看