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

    这是最具创造力的一节了,因为WPF中模板的功能非常强大。

    在WPF中,通过引入模板(Template)微软将数据和算法的“内容”与“形式”解耦了。WPF中的Template分为两大类:

    • ControlTemplate 是算法内容的表现形式,它决定了控件“长成什么样子”。
    • DataTemplate 是数据内容的表型形式,一条数据显示成什么样子。

    总而言之,ControlTemplate是控件的外衣,DataTemplate是数据的外衣。

    DateTemplate常用的地方有3处

    • ContentControl的ContentTemplate属性,相当于给ContentControl的内容穿衣服。
    • ItemsControl的ItemTemplate属性,相当于给ItemsControl的数据条目穿衣服。
    • GridViewColumn的CellTemplate属性,相当于给GridViewColumn的单元格里的数据穿衣服。

    请看例子

    <Window x:Class="DataTemplateSample.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:DataTemplateSample"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <local:AutomakerToLogoPathConveret x:Key="a2l"></local:AutomakerToLogoPathConveret>
            <local:NameToPhotoPathConverter x:Key="n2p"></local:NameToPhotoPathConverter>
            <DataTemplate x:Key="carDetailViewTemplate">
                <Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
                    <StackPanel Margin="5">
                        <Image Width="400" Height="250" Source="{Binding Name,Converter={StaticResource n2p}}"></Image>
                        <StackPanel Orientation="Horizontal" Margin="5,0">
                            <TextBlock Text="Name:" FontWeight="Bold" FontSize="20"/>
                            <TextBlock Text="{Binding Name}" FontSize="20" Margin="5,0"/>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" Margin="5,0">
                            <TextBlock Text="Automaker:" FontWeight="Bold"/>
                            <TextBlock Text="{Binding Automaker}" Margin="5,0"/>
                            <TextBlock Text="Year:" FontWeight="Bold" Margin="5,0"/>
                            <TextBlock Text="{Binding Year}" Margin="5,0"/>
                            <TextBlock Text="Top Speed:" FontWeight="Bold"/>
                            <TextBlock Text="{Binding TopSpeed}" Margin="5,0"/>
                        </StackPanel>
                    </StackPanel>
                </Border>
            </DataTemplate>
            <DataTemplate x:Key="carListItemViewTemplate">
                <Grid Margin="2">
                    <StackPanel Orientation="Horizontal">
                        <Image Grid.RowSpan="3" Width="64" Height="64" Source="{Binding Automaker,Converter={StaticResource a2l}}"/>
                        <StackPanel Margin="5,10">
                            <TextBlock Text="{Binding Name}" FontSize="16" FontWeight="Bold"/>
                            <TextBlock Text="{Binding Year}" FontSize="14"/>
                        </StackPanel>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </Window.Resources>
        <StackPanel Orientation="Horizontal" Margin="5">
            <UserControl ContentTemplate="{StaticResource carDetailViewTemplate}" Content="{Binding SelectedItem,ElementName=listBoxCars}"/>
            <ListBox x:Name="listBoxCars" Width="180" Margin="5,0" ItemTemplate="{StaticResource carListItemViewTemplate}" SelectionChanged="listBoxCars_SelectionChanged"/>
        </StackPanel>
    </Window>

    Car.cs

    class Car
        {
            public string Automaker { get; set; }
            public string Name { get; set; }
            public string Year { get; set; }
            public string TopSpeed { get; set; }
        }

    转换器

    public class AutomakerToLogoPathConveret:IValueConverter
        {
    
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                string uriStr = string.Format(@"Resources/Logos/{0}.jpg",(string)value);
                return new BitmapImage(new Uri(uriStr,UriKind.Relative));
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
        public class NameToPhotoPathConverter:IValueConverter
        {
    
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                string uriStr = string.Format(@"Resources/Images/{0}.jpg", (string)value);
                return new BitmapImage(new Uri(uriStr, UriKind.Relative));
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }

    使用DataTemplate完成了数据驱动UI的任务。

    在实际项目中,ControlTemplate主要有两大用武之地:

    • 通过更换ControlTemplate,获得更好的用户体验
    • 借助ControlTemplate可以使程序员和设计师并行工作

    如何设计ControlTemplate呢?首先必须知道每个控件的ControlTemplate,怎么看呢,用Blend4打碎它吧。

    俗话说得好,挑柿子得找软的捏,剖析控件也从简单的开始。TextBox和Button最简单。

     

    这是TextBox打碎后的结构。对TextBox点击右键-》编辑模板-》编辑副本

    可以看到代码如下

    <Window.Resources>
            <Style x:Key="MyTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
                <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Padding" Value="1"/>
                <Setter Property="AllowDrop" Value="true"/>
                <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
                <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
                <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TextBox}">
                            <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
                                <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Microsoft_Windows_Themes:ListBoxChrome>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>

    作为资源的不是单纯的ControlTemplate而是Style,就是说编辑ControlTemplate但实际上市把ControlTemplate包含在Style里,不知道微软以后会不会更正这个小麻烦。

    TemplateBinding,ControlTemplate最终将被运用到一个控件上,我们称这个控件为模板目标或模板化控件。ControlTemplate里的控件可以使用TemplateBinding将自己的属性值关联在目标控件的某个属性值上,必要的时候还可添加Converter。

    由ControlTemplate或DataTemplate生成的控件都是“由Template生成的控件”。ControlTemplate和DataTemplate都派生自FrameworkTemplate类,这个类有个名为FindName的方法供我们检索其内部控件,也就是说,只要我们能拿到Template,找到其内部控件就不成问题 。

  • 相关阅读:
    398. Random Pick Index
    382. Linked List Random Node
    645. Set Mismatch
    174. Dungeon Game
    264. Ugly Number II
    115. Distinct Subsequences
    372. Super Pow
    LeetCode 242 有效的字母异位词
    LeetCode 78 子集
    LeetCode 404 左叶子之和
  • 原文地址:https://www.cnblogs.com/HelloMyWorld/p/2933283.html
Copyright © 2011-2022 走看看