关于WPF中关于样式和模板的区别
Posted 蝸小牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于WPF中关于样式和模板的区别相关的知识,希望对你有一定的参考价值。
百度了下,改天整理。
WPF中关于样式和模板的区别:
回答一:
1.WPF样式
类似于Web应用程序中的CSS,在WPF中可以为控件定义统一的样式(Style)。样式属于资源的一种,例如为Button定义统一的背景颜色和字体:
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Yellow" />
</Style>
</Window.Resources>
<StackPanel>
<Button>Button A</Button>
</StackPanel>
在Style中定义的属性及值,影响到Window中的所有类型为Button的控件的样式
这种样式,类似于CSS中的类型选择器,为某种类型定义样式。
此外还可以在Style中加入x:Key属性,做为特定的样式(注意,这种也需要定义TargetType);
在第一个样式的基础上创建一个新样式可以达到这一目的,如下所示:<Window.Resources>
<Style x:Key="BigFontButtonStyle">
<Setter Property="Control.FontFamily" Value="Times New Roman" />
<Setter Property="Control.FontSize" Value="18" />
<Setter Property="Control.FontWeight" Value="Bold" />
</Style>
<Style x:Key="EmphasizedBigFontButtonStyle" BasedOn="{StaticResource BigFontButtonStyle}">
<Setter Property="Control.Foreground" Value="White" />
<Setter Property="Control.Background" Value="DarkBlue" />
</Style>
</Window.Resources>
以编程方式设置样式,若要以编程方式向元素分配命名样式,请从资源集合中获取该样式,然后将其分配给元素的 Style 属性。请注意,资源集合中的项是 Object
类型,因此,将检索到的样式分配给 Style 属性之前,必须将该样式强制转换为 Style。例如,若要对名为 textblock1 的
TextBlock 设置定义的 TitleText 样式,请执行以下操作:
textblock1.style=(style)Resources["TitleText"];
请注意,样式一旦应用,便会密封并且无法更改。如果要动态更改已应用的样式,必须创建一个新样式来替换现有样式。
2.wpf模板
当一个控件的外观不满足要求的时候,我们可以使用“控件模板”的方式更改控件的外观,WPF中的所有控件,只要有视觉外观,
就会有Template
property,且将此property的值设定为一个ControlTemplate对象。Button之所以看起来像Button就是因为受到了
ControlTemplate对象的直接影响。ControlTemplate对象定义了控件的完整外观,且你可以替换此对象。
抽象的FrameworkTemplate类型只定义了三个property。只读的Boolean
property用来标识此模板是否可以被修改。Resources
property的类型是ResourceDictionary,让我们定义一些只能够在模板内部使用的资源。第三个property最重要,叫做
visualTree,定义组成此控件外观的Element的layout。
ControlTemplate类型多加了两个property定义:TargetType用来指明,哪个类型的控件,适合应用到该模板;Triggers是Trigger对象的collection。
所有派生自ContentControl的类型都使用ContentPresenter类型的对象来显示它们的内容。ContentPresenter派
生自FrameworkElement,你可以在模板的视觉树内包含一个ContentPresenter对象,用来盛放模板中要放置的内容。
ContentPresenter
element负责显示所有“派生自ContentControl”控件的内容。ContentPresenter将这个世界分成两类对
象:UIElement的后代和非UIElement的后代,对于非UIElement的后代,ContentPresenter会调用对象的
ToString方法,用文本来展示该对象。这个功能让“派生自ContentControl”的控件可以用来显示任何种类的内容。
<Window.Resources>
<Style TargetType="Button" x:Key="ButtonStyle">
<!--设置按钮的默认的样式-->
<Setter Property="FontFamily" Value="Comic Sans MS"/>
</Setter>
<!--设置按钮的模板-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="{TemplateBinding Background}"/>
<ContentPresenter
Margin="5"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Margin="5" Style="{StaticResource ButtonStyle}"
Width="100" Height="100"
Content="My Button">
</Button>
<Button Margin="5" Width="200">Common Button</Button>
</StackPanel>。
回答2:
简单来说如果只需对控件进行小幅度修饰(调整大小、位置、字体、颜色等)就用style,如果需要改变控件的外观和行为就用controlTemplate(形状、事件触发如鼠标停留效果等)。在实际项目中,我们经常把模板(Template)定义在样式(Style)中,通过设置style。
比如:我要做一个用于地图缩放条的图片按钮,这时候通过style调整位置,用controltemplate设置按键形状。
<UserControl.Resources>
<Style x:Key="ZoomUpButton" TargetType="Button">
<Setter Property="Width" Value="23.5" />
<Setter Property="Height" Value="25.5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Width="23.5" Height="25.5">
<Image Source="/Resource/zoom+.png" Stretch="Fill" />
<ContentPresenter HorizontalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="2" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Button Style="{StaticResource ZoomUpButton}" />
再给个简单例子:一个带有on/off字样的单选框,选中的时候off字样隐去,没选中的时候on隐去
<Page.Resources>
<ControlTemplate x:Key="switch"TargetType="{x:Type CheckBox}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Width="96" Height="48" BorderBrush="Black" BorderThickness="1">
<Canvas Background="LightGray">
<TextBlock Canvas.Left="0" Canvas.Top="0" Foreground="Black" Text="Off" Margin="2" />
<TextBlock Canvas.Right="0" Canvas.Top="0 Foreground="Black" Text="On"
Margin="2" />
<Line Name="lineOff" StrokeThickness="8" Stroke="Black" X1="48" Y1="40"
X2="20" Y2="16" StrokeStartLineCap="Round" StrokeEndLineCap="Round" />
<Line Name="lineOn" StrokeThickness="8"Stroke="Black" X1="48" Y1="40"
X2="76" Y2="16" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Visibility="Hidden" />
</Canvas>
</Border>
<ContentPresenter Grid.Row="1"
Content="{TemplateBinding Content}"
HorizontalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="True">
<Setter TargetName="lineOff"
Property="Visibility"
Value="Hidden" />
<Setter TargetName="lineOn"
Property="Visibility"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Page.Resources>
<CheckBox Template="{StaticResource switch}"
Content="Master Switch"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
你可以在controltemplate中定义复杂的界面,比如:在复杂的treeview中,在controltemplate中定义左边带图片的样式以及右键菜单中,然后再datatemplate中定义层次结构。
实在不好意思,虽然知道一图胜过千言,但截图实在不方便,这两个例子你可以自己运行一下,我也是才学wpf不久,但看了一些英文版的教程后,才慢慢上手,wpf-4-unleashed挺不错的
回答3:如果你要修改Control的结构的话,就用 controlTemplate,比如你想在Button里加一个Grid。在修改样式上,style 和 controlTemplate没有什么不同,都是对控件样式进行规范化,最终目的都是修改控件的Template。只不过用controlTemplate时,会在Resources里生成一个static 的ControlTemplate。但是如果是对数据进行规范化,就只能用数据模板了(DataTemplate),Style就不行了。
以上是关于关于WPF中关于样式和模板的区别的主要内容,如果未能解决你的问题,请参考以下文章
SQL中关于JoinInner JoinLeft JoinRight JoinFull JoinOn Where区别
2022-04-20 WPF面试题 WPF中的样式和资源有什么区别?