在前一章,我们介绍了样式的概念,我们使用了本地定义样式的一个基础示例,它针对特定类型的控件 - TextBlock。 但是,样式可以在几个不同的范围中定义,具体取决于您希望在何处以及如何使用它们,甚至可以将样式限制为仅在您明确需要的控件上使用。 在本章中,我将向您展示定义样式的所有不同方式。
您可以直接在控件上定义样式,如下所示:
<Window x:Class="WpfTutorialSamples.Styles.ControlSpecificStyleSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ControlSpecificStyleSample" Height="100" Width="300">
<Grid Margin="10">
<TextBlock Text="Style test">
<TextBlock.Style>
<Style>
<Setter Property="TextBlock.FontSize" Value="36" />
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Window>
在本例中,样式只影响这个特定的TextBlock控件,所以为什么要这么麻烦? 嗯,在这种情况下,根本没有任何意义。 我可以用TextBlock控件上的单个FontSize属性替换所有额外的标记,但正如我们稍后将看到的,样式可以做的不仅仅是设置属性,例如样式触发器可以使上述示例在实际应用程序中很有用。但是,您定义的大多数样式可能会在更高的范围。
使用控件的Resources部分,可以面向此控件的子控件(以及这些子控件的子控件等)。 这基本上就是我们在上一章的介绍示例中所做的,它看起来像这样:
<Window x:Class="WpfTutorialSamples.Styles.SimpleStyleSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SimpleStyleSample" Height="200" Width="250">
<StackPanel Margin="10">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</StackPanel.Resources>
<TextBlock>Header 1</TextBlock>
<TextBlock>Header 2</TextBlock>
<TextBlock Foreground="Blue">Header 3</TextBlock>
</StackPanel>
</Window>
这对于更多本地样式需求非常有用。 例如在对话框中执行此操作非常有意义,您只需要一组控件看起来相同,而不是在每个控件上设置各个属性。
范围层次结构中的下一步是定义Window资源中的样式。 这与StackPanel的完全相同,但是在您希望将特定样式应用于窗口中的所有控件(或者UserControl)的情况下,它非常有用,而不仅仅是在特定控件本地中。 这是一个修改过的例子:
<Window x:Class="WpfTutorialSamples.Styles.WindowWideStyleSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowWideStyleSample" Height="200" Width="300">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</Window.Resources>
<StackPanel Margin="10">
<TextBlock>Header 1</TextBlock>
<TextBlock>Header 2</TextBlock>
<TextBlock Foreground="Blue">Header 3</TextBlock>
</StackPanel>
</Window>
正如您所看到的,结果完全相同,但它确实意味着您可以在窗口中的任何位置放置控件,并且样式仍然适用。
如果您希望在不同的窗口中使用整个应用程序统一的样式,则可以为整个应用程序定义它。 这是在Visual Studio为您创建的App.xaml文件中完成的,并且就像在窗口范围的示例中一样:
App.xaml
<Application x:Class="WpfTutorialSamples.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Styles/WindowWideStyleSample.xaml">
<Application.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</Application.Resources>
</Application>
Window
<Window x:Class="WpfTutorialSamples.Styles.WindowWideStyleSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ApplicationWideStyleSample" Height="200" Width="300">
<StackPanel Margin="10">
<TextBlock>Header 1</TextBlock>
<TextBlock>Header 2</TextBlock>
<TextBlock Foreground="Blue">Header 3</TextBlock>
</StackPanel>
</Window>
您可以很好地控制如何以及在何处将样式应用于控件,从本地样式到应用程序范围的样式,可以帮助您在整个应用程序中获得一致的外观,但到目前为止,我们所有的样式都针对特定的控件类型,然后所有这些控件都使用了它。 但并非必须如此。
通过在样式上设置x:Key属性,告诉WPF,只有您在特定控件上显式引用它时,才使用此样式。 让我们尝试一下这种情况的例子:
<Window x:Class="WpfTutorialSamples.Styles.ExplicitStyleSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ExplicitStyleSample" Height="150" Width="300">
<Window.Resources>
<Style x:Key="HeaderStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</Window.Resources>
<StackPanel Margin="10">
<TextBlock>Header 1</TextBlock>
<TextBlock Style="{StaticResource HeaderStyle}">Header 2</TextBlock>
<TextBlock>Header 3</TextBlock>
</StackPanel>
</Window>
请注意,即使TargetType设置为TextBlock,并且为整个窗口定义了样式,但只有中间的TextBlock(我明确引用HeaderStyle样式)才使用该样式。 这允许您定义以特定控件类型为目标的样式,但仅在需要它的位置使用它。
WPF样式允许您轻松地在整个应用程序中重复使用某些外观。 使用x:Key属性,您可以决定是否显式引用样式才能生效,或者它是否应该以所有控件为目标。