WPF中的Template模板

本文深入探讨WPF中的模板机制,包括ControlTemplate和DataTemplate的使用方式,并讲解如何利用样式来增强控件表现力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

d## WPF中的模板Template ##
WPF中通过引入模板将数据和算法的内容和形式解耦
ControlTemplate 是算法的内容的表现形式,决定了控件长成什么样子,让程序员在控件原有的内部逻辑基础上扩展自己的逻辑
DataTemplate 是数据的内容的表现形式,数据显示成什么形式,外观

DataTemplate
常用在三处:
ContentControl的ContentTemplate属性,
ItemsControl的ItemTemplate属性,
GridViewColumn的CellTemplate属性

public class AutomakerToLogoPathConverter:IValueConverter{
    public object Convert(object value,Type targetType,object parameter,CultureInfo culture){
        string uriStr = string.Format(@"/Resources/Logos/{0}.png",(stringvalue));
        return new BitmapImage(new Uri(uriStr,UriKind.Relative));
    }
    publiuc ConvertBack(object value,Type targetType,object parameter,CultureInfo culture){
    throw new NotImplementedException();
    }
}

public class NameToPhotoPathConverter:IValueConverter{
    public object Convert(object value,Type targetType,object parameter,CultureInfo culture){
        string uriStr = string.Format(@"/Resources/Images/{0}.png",(stringvalue));
        return new BitmapImage(new Uri(uriStr,UriKind.Relative));
    }
    publiuc ConvertBack(object value,Type targetType,object parameter,CultureInfo culture){
    throw new NotImplementedException();
    }
}
...
<Window
    ...>
    <Window.Resources>
        <local:AutomakerToLogoPathConverter x:Key = "a2l"/>
        <local:NameToPhotoPathConverter x:Key = "n2p"/>
        <DataTemplate x:Key = "carDetailViewTemplate"
            <Stackpanel>
                ....
                <Image Width = "400" Height = "250"
                    Source = "{Binding Name,Converter{StaticResource n2p}}"/>
                ...
            </Stackpanel>
            ...
        </DataTemplate> 
        <DataTemplate x:Key = "carListViewTemplate"
            ...
        </DataTemplate> 
    </Window.Resources>
    <StackPanel Orientation = "Horizontal" Margin = "5">
        <UserControl ContentTemplate = "{StaticResource carDetailViewTemplate}"
                     Content = "{Binding SelectedItem,ElementName = listBoxCars}"/>
        <ListBox x:Name = "listBoxCars" Width = "180" margin= “50”
                 ItemTemplate = "{StaticResource0 carListViewTemplate}"/>
    </StackPanel >
</Window>
    ...
private void InitialCarList(){
    List<Car> carList = new List<Car>(){
        new Car{Automaker = "tfewaf",Name = "fase",Year = "1964",TopSpeed = "131"},
        new Car{Automaker = "tfewaf",Name = "fase",Year = "1964",TopSpeed = "131"},
        new Car{Automaker = "tfewaf",Name = "fase",Year = "1964",TopSpeed = "131"},
        new Car{Automaker = "tfewaf",Name = "fase",Year = "1964",TopSpeed = "131"},
        new Car{Automaker = "tfewaf",Name = "fase",Year = "1964",TopSpeed = "131"}
    }
    this.lisrBoxCars.ItemsSource = carList;
}

ControlTemplate
用处:
更换ControlTemplate改变控件外观,使之具有更优的用户体验及外观。
借助ControlTemplate让程序员和设计师并行工作。

打开Blend开始编辑
组件上右键,编辑模板,编辑副本

ControlTemplate可以放在三个地方Application的资源字典中,界面元素的资源字典中,外部XMAL文件中。

ControlTemplate 在Blend中通过可视化界面编辑模板即可。

ControlTemplate 和DataTemplate 的区别

ControlTemplate :决定控件的外观
DataTemplate : 决定数据的外观。与具体数据相关的控件,比如需要Binding数据的控件,数据转换Converter。
DataTemplate 是 ControlTemplate 的一颗子树。

如何找控件树根:
控件的TemplateParent属性的值就是应用了模板的控件。
控件的TemplateBinding的数据源就是应用类这个模板的目标控件。

Template的应用
1. 逐个设置控件的Template/ContentTemplate/ItemsTemplate/CellTemplate 等属性。
2. 把Template应用在某个类型的控件或数据上。

例:

<Window.Resources>
    <DataTemplate DataType = "{x:Type local:Unit}">
        <StackPanel>
            <TextBlock Text = "{Binding Price}"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>
    ...
public class Unit{
    public int Price{get;set;}
    public string Year{get;set;}
}

DataTemplate的目标数据类型和ListBox的条目类型都是Unit
DataTemplate会自动加载到所有Unit类型对象上

<Window.Resources>
    <DataTemplate DataType = "Unit">
        <StackPanel>
            <TextBlock Text = "{Binding XPath = @Price}"/>
            <TextBlock Text = "{Binding XPath = @Year}"/>
        </StackPanel>
    </DataTemplate>
    ...
    <XmlDataProvider x:Key = "ds" XPath="Unites/Unit">
        <x:XData>
            <Units xmlns = "">
                <Unit Year = "2001" Price = "100"/>
                ...
            </Units>
        </x:XData>  
    </XmlDataProvider>
</Window.Resources>
    ...
    <ListBox ItemSource="{Binding Source = {StaticResource de}}"/>
    <ComboBox ItemSource="{Binding Source = {StaticResource de}}"/>

将XML作为数据源

<HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath = Student}">
    <TextBlock Text="{Binding XPath=@Name}"
</HierarchicalDataTemplate>

找到Template中的组件

ControlTemplate

TextBox tb = this.uc.Template.FindName("textBox1",this.uc) as Textbox;
tb.Text="Hello Wpf";
StackPanel sp = tb.Parent as StackPanel;
(sp.children[1] as TextBox).Text = "Hello Template";
(sp.children[1] as TextBox).Text = "Hello Template";

DataTemplate
例1:

<ContentPresenter ContentTemplate="{StaticResource stuDT}"/>
...
TextBox tb = this.uc.ContentTemplate.FindName("textBox1",this.cp) as Textbox;
MessageBox.Show(tb.Text);

例2:

private void TextBoxNAme_GotFocus(object sender,RoutedEventArgs e){
    TextBox tb = e.OriginalSource as TextBox;//获取事件发起的源头
    ContentPresenter cp = tb.TemplatedParent as ContentPresenter;//获取模板目标
    Student stu = cp.Content as Student;//获取业务逻辑
    this.listViewStudent.SelectedItem = stu;//设置ListView的选中项
    //访问界面元素
    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.Get(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,分别表示控件的静态外观风格和行为风格。

Setter 设置属性值
例:

<Setter Property = "FontSize" Value="24"/>
<Setter Property = "FontStyle" Value="Italic"/>
<Setter Property = "Template" Value="ControlTemplate"/>

Trigger 触发器
一般由用户操作触发。
事件触发型EventTrigger,数据变化触发型Trigger/DataTrigger,多条件触发型MultiTrigger/MultiDataTrigger。

1.基本触发器
Property 检测的属性,Value 触发的条件
Setters触发后执行的动作,比如换肤
例:

<Style Targettype = "CheckBox">
    <Style.Triggers>
        <Trigger Property = "IsChecked" Value="true">
            <Trigger.Setters>
                <Setter Property="FontSize" value="20"/>
                <Setter Property="Foreground" value="Orange"/>
            </Trigger.Setters>
        </Trigger>
    </Style.Triggers>
</Style>
    ...
<StackPanle>
    <CheckBox Content="check1"/>
    <CheckBox Content="check2"/>
    <CheckBox Content="check3"/>
    <CheckBox Content="check4"/>
</StackPanle>

2.MultiTrigger 多条件同时成立才触发,比Trigger多一个Conditions属性,需要成立的条件就存储在此集合中。

...
<MultiTrigger.Conditions>
    <Coadition Property="isChecked" Value="true"/>
    <Coadition Property="Content" Value="Hello"/>
</MultiTrigger.Conditions>
...

3.DataTrigger Binding属性的值与Value的值一样触发

<DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self},Path=Text.Length,Converter={StaticResource cvt2r}}"
Value="false">
//在cvtr中进行判断操作
    <Setter.../>
    <Setter.../>
    <Setter.../>
</DataTrigger>

4.MultiDataTrigger 多数据条件同时满足时触发

...
<MultiDataTrigger>
    <MultiDataTrigger.Conditions>
        <Condition Binding="{Binding Path=ID}" Value="2"/>
        <Condition Binding="{Binding Path=Name}" Value="Tom"/>
    </MultiDataTrigger.Conditions>
    <MultiDataTrigger.Setters>
    ...
    </MultiDataTrigger.Setters>
</MultiDataTrigger>

5.EventTrigger
事件触发,比较特殊。它由事件触发,而且触发后不是应用一组setter而是执行一段动画。
UI层的动画效果往往与EventTrigger关联。
例如Button的MouseEnter和MouseLeave的事件触发器。

例:

<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="Width"/>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>

不仅Style中可以使用触发器,Template中同样可以使用触发器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值