🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,优快云博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年优快云博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏
🚀前言
WPF中的模板(template)是一种定义控件外观和行为的方式。模板包含控件结构和样式,允许您自定义控件的外观和行为。模板可以包含多个元素,例如文本、图像、图形、动画等。模板通常使用XAML(可扩展应用程序标记语言)编写,并可以在应用程序中定义和重用。通过使用模板,您可以创建自定义控件,或者修改现有控件的外观和行为,以满足特定需求。
WPF中模板处理包括以下步骤:
-
定义模板:在XAML中定义模板,包括控件和其他元素的结构、样式和行为。
-
应用模板:将模板应用到控件样式中,使用控件的Template属性。
-
实例化模板:在运行时将模板实例化为控件的视觉子树,并绑定到控件的逻辑子树上。
-
属性值继承:模板应用后,控件会继承模板中的属性值,如背景颜色和字体大小等。
-
控件模板附加事件:在控件模板中,可以使用附加事件来添加和处理事件。
模板处理是WPF中控件外观和行为的基础,通过使用模板,可以轻松地定制控件的外观和行为,实现更好的用户体验。
WPF中的常见模板类型包括:
- 控件模板(ControlTemplate):控制WPF控件的外观和行为,例如Button、TextBox等。
- 数据模板(DataTemplate):定义WPF控件如何展示数据,例如ListView、ComboBox、TreeView等。
- 页模板(PageTemplate):定义WPF中页面的布局和设计,包括Header、Footer、Sidebar等。
- 视图模板(ViewTemplate):定义MVC(Model-View-Controller)、MVVM(Model-View-ViewModel)等设计模式中视图的格式和布局方式。
- 消息模板(MessageTemplate):自定义WPF中的通知消息样式和行为,例如弹出框、提示框等。
- 资源模板(ResourceTemplate):定义WPF中一些通用的资源,例如颜色、字体、样式等,供其他模板使用。
🚀一、模板选择器
🔎1.模板选择器的概念
模板选择器(Template Selector)是WPF中一种用于根据数据模型动态选择不同显示样式的机制。通过模板选择器,可以在列表或其他控件中按需要选择使用不同的模板来呈现数据。
在WPF中,模板选择器通常继承自DataTemplateSelector类,通过实现其中的SelectTemplate方法来决定使用哪个数据模板。SelectTemplate方法接收一个数据项和一个容器对象作为参数,可以根据数据项的类型或其他属性来决定使用哪个数据模板,并将其返回。
一般来说,模板选择器的使用流程如下:
- 创建多个数据模板,每个模板对应不同的数据类型或属性。
- 继承DataTemplateSelector类,实现SelectTemplate方法。
- 在需要使用模板选择器的控件中,将选择器赋值给DataTemplateSelector属性。
- 控件会调用选择器的SelectTemplate方法,根据数据项选择对应的数据模板。
通过这种方式,可以实现根据不同的数据类型或属性来动态选择使用不同的样式模板,从而实现更加灵活和个性化的数据呈现效果。
🔎2.模板选择器的元素
WPF中模板选择器的元素包括:
-
DataTemplate:用于定义界面元素的模板。
-
ContentPresenter:用于显示模板的内容。
-
Style:用于定义界面元素的外观和行为。
-
ControlTemplate:用于定义控件的模板。
-
Trigger:用于在特定的条件下更改控件的外观和行为。
-
TemplateBinding:用于在模板中绑定控件的属性。
🔎3.模板选择器的使用
🦋3.1 数据模板选择器
在WPF中,可以使用ItemTemplateSelector来选择一个特定的模板,根据数据源中的属性值动态地为每个项设置不同的模板。
以下是一个简单的示例:
- 首先,创建一个数据模型类,其中包含一个Name属性和一个IsSelected属性:
public class MyData
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
- 创建一个ItemTemplateSelector类,该类包含两个模板:一个用于选定项,另一个用于未选定项。在这个示例中,我们使用DataTemplate作为模板:
public class MyItemTemplateSelector : DataTemplateSelector
{
public DataTemplate SelectedTemplate { get; set; }
public DataTemplate UnselectedTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var data = item as MyData;
if (data != null && data.IsSelected)
{
return SelectedTemplate;
}
return UnselectedTemplate;
}
}
- 在XAML中,创建一个ListBox,设置它的ItemTemplateSelector为我们刚才创建的MyItemTemplateSelector:
<ListBox ItemsSource="{Binding MyDataList}">
<ListBox.ItemTemplateSelector>
<local:MyItemTemplateSelector>
<local:MyItemTemplateSelector.SelectedTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" Foreground="Red" FontWeight="Bold"/>
</DataTemplate>
</local:MyItemTemplateSelector.SelectedTemplate>
<local:MyItemTemplateSelector.UnselectedTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</local:MyItemTemplateSelector.UnselectedTemplate>
</local:MyItemTemplateSelector>
</ListBox.ItemTemplateSelector>
</ListBox>
在这里,我们绑定了MyDataList到ListBox的ItemsSource属性上,然后使用MyItemTemplateSelector来选择模板。在MyItemTemplateSelector中,我们定义了两个模板:SelectedTemplate和UnselectedTemplate。如果MyData的IsSelected属性为true,SelectedTemplate将显示一个粗体红色文本块,否则,UnselectedTemplate将显示一个普通的文本块。
通过这个简单示例,您可以了解如何使用ItemTemplateSelector在WPF中为每个项动态地选择不同的模板。
🦋3.2 样式模板选择器
WPF中样式模板选择器是一个强大的功能,它可用于根据特定条件或属性值选择不同的样式或模板。它通常包含以下步骤:
-
定义样式或模板:在XAML中定义一组样式或模板。每个样式或模板都拥有一个键(Key)来标识它。
-
定义样式或模板选择器:在XAML中定义一个继承自StyleSelector的样式选择器类。在该类中,可以实现逻辑来根据某些条件或属性值选择特定的样式或模板。
-
将样式或模板与样式选择器关联:在XAML中,将样式选择器分配给控件的StyleSelector属性。在代码中,可以将样式选择器分配给控件的StyleSelector属性。
例如,以下示例演示如何使用样式模板选择器为ListBox中的不同项选择不同的样式:
在XAML定义样式:
<Window.Resources>
<Style x:Key="Style1" TargetType="ListBoxItem">
<Setter Property="Background" Value="Yellow"/>
</Style>
<Style x:Key="Style2" TargetType="ListBoxItem">
<Setter Property="Background" Value="Green"/>
</Style>
</Window.Resources>
定义样式选择器:
public class StyleSelectorExample : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
if (item is string)
{
string str = item as string;
if (str.StartsWith("A"))
return (Style)Application.Current.Resources["Style1"];
else
return (Style)Application.Current.Resources["Style2"];
}
return base.SelectStyle(item, container);
}
}
将样式选择器与ListBox关联:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemContainerStyleSelector>
<local:StyleSelectorExample />
</ListBox.ItemContainerStyleSelector>
</ListBox>
在此示例中,样式选择器会检查ListBox的每个项。如果项是以字母“A”开头的字符串,则应用Style1样式,否则应用Style2样式。
🔎4.相关案例
<Window x:Class="Zhaoxi.TemplateDemo.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Zhaoxi.TemplateDemo"
mc:Ignorable="d"
Title="Window2" Height="450" Width="800">
<Window.Resources>
<local:Person Name="Jovan" Age="29" x:Key="person"/>
<x:Array x:Key="array" Type="local:Person">
<local:Person Name="Jovan" Age="29"/>
<local:Person Name="Clay" Age="28"/>
<local:Person Name="Ace" Age="31"/>
<local:Person Name="Leah" Age="29"/>
</x:Array>
<DataTemplate x:Key="normalDt">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text=":"/>
<TextBlock Text="{Binding Age}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="highlightDt">
<StackPanel TextBlock.Foreground="Red">
<TextBlock Text="{Binding Age}"/>
<TextBlock Text=":"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
<Style TargetType="ListViewItem">
<Setter Property="FontSize" Value="30"/>
</Style>
</Window.Resources>
<Grid>
<!--StackPanel>
<Button Height="50" FontSize="30" Content="{StaticResource person}"/>
<Button Height="50" FontSize="30" Content="{StaticResource person}" ContentTemplate="{StaticResource dt}"/>
</StackPanel>-->
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{DynamicResource array}">
<ListView.ItemTemplateSelector>
<local:PersonDataTemplateSelector NormalTemplate="{StaticResource normalDt}"
HightlightTemplate="{StaticResource highlightDt}"
MinAge="28" MaxAge="30"
PropName="Name" NameValue="Ace"/>
</ListView.ItemTemplateSelector>
</ListView>
<ListView ItemsSource="{DynamicResource array}" Grid.Column="1">
<ListView.ItemTemplateSelector>
<local:PersonDataTemplateSelector NormalTemplate="{StaticResource normalDt}"
HightlightTemplate="{StaticResource highlightDt}"
MinAge="29" MaxAge="31"
PropName="Name" NameValue="Ace"/>
</ListView.ItemTemplateSelector>
</ListView>
</Grid>
</Window>
public class PersonDataTemplateSelector : DataTemplateSelector
{
public DataTemplate NormalTemplate { get; set; }
public DataTemplate HightlightTemplate { get; set; }
public int MinAge { get; set; }
public int MaxAge { get; set; }
public string PropName { get; set; }
public string NameValue { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
Person person = item as Person;
var result = person.GetType().GetProperty(PropName).GetValue(person);
//if (person.Age > MinAge && person.Age <= MaxAge)
//{
// return HightlightTemplate;
//}
if (result.ToString() == NameValue)
{
return HightlightTemplate;
}
return NormalTemplate;
}
}
🚀感谢:给读者的一封信
亲爱的读者,
我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。
如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。
我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。
如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。
再次感谢您的阅读和支持!
最诚挚的问候, “愚公搬代码”