目录

资源键Key

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和带有TargetTypeStyle属于特殊情况,他们本身带有隐式键。

例:

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>

这两种方法都是使用了隐式的资源键,在设计器中我们也能实时的看到效果,但是当程序执行的时候其结果却和预想的不一样:

/wpf_resource_key/key1.png

运行时窗体的背景并不是红色!

这或许是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。但运行结果却是无效的样式。

/wpf_resource_key/key2.png

这是因为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>

这时候再运行程序就能看到正确的结果了:

/wpf_resource_key/key3.png