关于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区别

银联卡中关于CVN/CVN2/ICVN的区别

2022-04-20 WPF面试题 WPF中的样式和资源有什么区别?

2022-04-20 WPF面试题 WPF中的样式和资源有什么区别?

devexpress与winform区别

WPF 中 DataTemplate 中的 x:Key、x:Name 和 x:UID 有啥区别?