如何定义和引用 WPF 资源 (WPF .NET)

此示例演示如何定义资源并引用它。 可以通过 XAML 或代码引用资源。

重要

面向 .NET 7 和 .NET 6 的桌面指南文档正在撰写中。

XAML 示例

以下示例定义两种类型的资源:一种 SolidColorBrush 资源和多个 Style 资源。

<Window.Resources>
    <SolidColorBrush x:Key="MyBrush" Color="#05E0E9"/>
    <Style TargetType="Border">
        <Setter Property="Background" Value="#4E1A3D" />
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="BorderBrush">
            <Setter.Value>
                <LinearGradientBrush>
                    <GradientStop Offset="0.0" Color="#4E1A3D"/>
                    <GradientStop Offset="1.0" Color="Salmon"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="TextBlock" x:Key="TitleText">
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="Foreground" Value="#4E87D4"/>
        <Setter Property="FontFamily" Value="Trebuchet MS"/>
        <Setter Property="Margin" Value="0,10,10,10"/>
    </Style>
    <Style TargetType="TextBlock" x:Key="Label">
        <Setter Property="HorizontalAlignment" Value="Right"/>
        <Setter Property="FontSize" Value="13"/>
        <Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
        <Setter Property="FontFamily" Value="Arial"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Margin" Value="0,3,10,0"/>
    </Style>
</Window.Resources>

资源

SolidColorBrush 资源 MyBrush 用于提供多个属性的值,每个属性都采用 Brush 类型的值。 此资源通过 x:Key 值引用。

<Border>
    <StackPanel>
        <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
        <TextBlock Style="{StaticResource Label}">Label</TextBlock>
        <TextBlock HorizontalAlignment="Right" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
        <Button HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
        <Ellipse HorizontalAlignment="Center" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="10" />
    </StackPanel>
</Border>

在前面的示例中,通过 StaticResource 标记扩展访问 MyBrush 资源。 资源分配给可接受所定义资源的类型的属性。 在此示例中为 BackgroundForegroundFill 属性。

资源字典中的所有资源都必须提供键。 但是,在定义样式时,它们可以省略键,如下一部分中所述。

如果使用 StaticResource 标记扩展从其他资源中引用资源,则也会按照在字典中找到的顺序请求资源。 请确保在集合中定义的任何资源都早于请求该资源的位置。 有关详细信息,请参阅静态资源

如有必要,可通过使用 DynamicResource 标记扩展在运行时引用资源来解决资源引用的严格创建顺序,但你需要知道,这种 DynamicResource 技术会影响性能。 有关详细信息,请参阅动态资源

样式资源

以下示例隐式和显式引用样式:

<Border>
    <StackPanel>
        <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
        <TextBlock Style="{StaticResource Label}">Label</TextBlock>
        <TextBlock HorizontalAlignment="Right" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
        <Button HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
        <Ellipse HorizontalAlignment="Center" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="10" />
    </StackPanel>
</Border>

在前面的代码示例中,Style 资源 TitleTextLabel 都以特定控件类型为目标。 在本例中,它们都以 TextBlock 为目标。 当该样式资源由其 Style 属性的资源键引用时,这些样式将在目标控件上设置各种不同的属性。

样式虽然以 Border 控件为目标,但并不定义键。 省略键时,TargetType 属性所针对的对象类型将隐式用作样式的键。 当样式键控为某个类型时,只要这些控件在该样式的范围内,它就将成为该类型的所有控件的默认样式。 有关详细信息,请参阅样式、DataTemplate 和隐式键

代码示例

以下代码片段演示如何通过代码创建和设置资源

创建样式资源

创建资源并将其分配给资源字典可以随时发生。 但是,只有使用 DynamicResource 语法的 XAML 元素才会在创建后使用资源自动更新。

例如,请看下面的窗口。 它有四个按钮。 第四个按钮使用 DynamicResource 来设置自己的样式。 但是,此资源尚不存在,因此它看起来就像一个普通的按钮:

<StackPanel Margin="5">
    <Button Click="Button_Click">Explicitly Styled</Button>
    <Button>Unstyled</Button>
    <Button>Unstyled</Button>
    <Button Style="{DynamicResource ResourceKey=buttonStyle1}">Dynamically Styled</Button>
</StackPanel>

A window before a style is applied to a button

单击第一个按钮并执行以下任务时,将调用以下代码:

  • 创建一些颜色以便于参考。
  • 创建新样式。
  • 为样式分配资源库。
  • 将样式作为名为 buttonStyle1 的资源添加到窗口的资源字典中。
  • 将样式直接分配给引发 Click 事件的按钮。
private void Button_Click(object sender, RoutedEventArgs e)
{
    // Create colors
    Color purple = (Color)ColorConverter.ConvertFromString("#4E1A3D");
    Color white = Colors.White;
    Color salmon = Colors.Salmon;

    // Create a new style for a button
    var buttonStyle = new Style(typeof(Button));

    // Set the properties of the style
    buttonStyle.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(purple)));
    buttonStyle.Setters.Add(new Setter(Control.ForegroundProperty, new SolidColorBrush(white)));
    buttonStyle.Setters.Add(new Setter(Control.BorderBrushProperty, new LinearGradientBrush(purple, salmon, 45d)));
    buttonStyle.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(5)));

    // Set this style as a resource. Any DynamicResource tied to this key will be updated.
    this.Resources["buttonStyle1"] = buttonStyle;

    // Set this style directly to a button
    ((Button)sender).Style = buttonStyle;
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)

    'Create colors
    Dim purple = DirectCast(ColorConverter.ConvertFromString("#4E1A3D"), Color)
    Dim white = Colors.White
    Dim salmon = Colors.Salmon

    'Create a new style for a button
    Dim buttonStyle As New Style()

    'Set the properties of the style
    buttonStyle.Setters.Add(New Setter(Control.BackgroundProperty, New SolidColorBrush(purple)))
    buttonStyle.Setters.Add(New Setter(Control.ForegroundProperty, New SolidColorBrush(white)))
    buttonStyle.Setters.Add(New Setter(Control.BorderBrushProperty, New LinearGradientBrush(purple, salmon, 45D)))
    buttonStyle.Setters.Add(New Setter(Control.BorderThicknessProperty, New Thickness(5)))

    'Set this style as a resource. Any DynamicResource looking for this key will be updated.
    Me.Resources("buttonStyle1") = buttonStyle

    'Set this style directly to a button
    DirectCast(sender, Button).Style = buttonStyle

End Sub

运行代码后,窗口将更新:

A window after a style is applied to a button

请注意,第四个按钮的样式已更新。 该样式已自动应用,因为按钮使用 DynamicResource 标记扩展来引用尚不存在的样式。 创建样式并将其添加到窗口的资源后,该样式将应用于按钮。 有关详细信息,请参阅动态资源

查找资源

下面的代码遍历运行其中的 XAML 对象的逻辑树,以查找指定的资源。 资源可以在对象本身(资源的父级)上定义,直到到达根(即应用程序本身)。 下面的代码从按钮本身开始搜索资源:

myButton.Style = myButton.TryFindResource("buttonStyle1") as Style;
myButton.Style = myButton.TryFindResource("buttonStyle1")

显式引用资源

引用资源时,通过搜索或创建资源,可以将其直接分配给属性:

// Set this style as a resource. Any DynamicResource tied to this key will be updated.
this.Resources["buttonStyle1"] = buttonStyle;
'Set this style as a resource. Any DynamicResource looking for this key will be updated.
Me.Resources("buttonStyle1") = buttonStyle

另请参阅