1. 什么是资源键
资源键x:Key用作创建和引用资源的唯一标识,作用类似于名称,常出现在ResourceDictionary中且要求必须为 ResourceDictionary 内的每项定义一个键。
例:
1 2 3 4 5 6
| <ResourceDictionary> <LinearGradientBrush x:Key="fadeBrush"> <GradientStop Color="Red" Offset="0"/> <GradientStop Color="Gray" Offset="1"/> </LinearGradientBrush> </ResourceDictionary>
|
但带有DataType的数据模板DataTemplate和带有TargetType的Style属于特殊情况,他们本身带有隐式键。
例:
1 2 3 4
| <Style TargetType="{x:Type Button}"> <Setter Property="Background" Value="Azure"> </Setter> </Style>
|
在这种情况下,该style是应用中所有 Button 控件的隐式样式。但是资源键的使用并不是这么简单,下面通过两个例子展示资源键使用过程中很可能被忽略的地方。
2. 窗体对资源字典的引用
假设有这样一个需求:给系统中的所有window设置红色背景。
能够想到的方法很多,下面列出几种。
方法1:
1.新建资源字典Dictionary1.xaml
1 2 3 4 5 6 7
| <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="{x:Type Window}"> <Setter Property="Background" Value="Red"> </Setter> </Style> </ResourceDictionary>
|
2.在App.xaml
中添加字典引用
1 2 3
| <Application.Resources> <ResourceDictionary Source="Dictionary1.xaml" /> </Application.Resources>
|
方法2:
直接在App.xaml
中添加样式
1 2 3 4 5 6
| <Application.Resources> <Style TargetType="{x:Type Window}"> <Setter Property="Background" Value="Red"> </Setter> </Style> </Application.Resources>
|
这两种方法都是使用了隐式的资源键,在设计器中我们也能实时的看到效果,但是当程序执行的时候其结果却和预想的不一样:
运行时窗体的背景并不是红色!
这或许是VS设计器的bug,但怎样才能实现这个需求呢?我们只需要给这个Style添加显式的资源键,并在Window中设置Style为动态资源且引用这个资源键即可:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <Style x:Key="bg" TargetType="{x:Type Window}"> <Setter Property="Background" Value="Red"> </Setter> </Style>
<Window x:Class="WpfApplication19.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Style="{DynamicResource bg}" Width="525" > <Grid/> </Window>
|
这时候再运行程序,结果就正常了。
所以在WPF中对于窗体Window,不能以隐式的方式使用资源键,必须显式声明和引用。
3. 数据模板内控件样式的引用
在DataTemplate中给控件设置Style,我们直接看这个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <Window.Resources> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Background" Value="Red"></Setter> </Style> <DataTemplate DataType="{x:Type local:Person}"> <TextBlock Text="{Binding Name}" /> </DataTemplate> </Window.Resources>
<Grid> <ItemsControl ItemsSource="{Binding Persons}" Grid.Column="0" Margin="0,0,0,163"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </Grid>
|
在上面的例子中创建了一个DataTemplate,它包含一个TextBlock,我们想给这个TextBlock设置红色背景,所以又添加了一个有隐式键的Style。但运行结果却是无效的样式。
这是因为DataTemplate不能读取和它“平级”的Style,只能把这个Style放在它的下级DataTemplate.Resources
或全局Application.Resources
中。
例:
1 2 3 4 5 6 7 8
| <DataTemplate DataType="{x:Type local:Person}"> <DataTemplate.Resources> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Background" Value="Red"></Setter> </Style> </DataTemplate.Resources> <TextBlock Text="{Binding Name}" /> </DataTemplate>
|
或
1 2 3 4 5
| <Application.Resources> <Style TargetType="{x:Type TextBlock}"> <Setter Property="Background" Value="Red"></Setter> </Style> </Application.Resources>
|
这时候再运行程序就能看到正确的结果了: