WPF入门到跪下 第三章 基础知识-字典与样式

资源字典

一、简单使用

资源字典的使用较为简单,主要有以下2个步骤:

  • 右键项目→添加→新建资源字典,然后在资源字典中编写资源。
    WPF入门到跪下 第三章 基础知识-字典与样式_第1张图片

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:sys="clr-namespace:System;assembly=mscorlib"
                        >
        <sys:Double x:Key="value">100</sys:Double>
        
    </ResourceDictionary>
    
  • 在需要使用的XAML文件中引入资源字典并使用

    <Window ......>
        <Window.Resources>
            <ResourceDictionary Source="pack://application:,,,/WPFResource;component/MyDictionary.xaml"></ResourceDictionary>
        </Window.Resources>
        <Border Height="{StaticResource value}">
        </Border>
    </Window>
    

有一点需要知道的是,我们在定义资源的时候,定义的资源默认就是放在ResourceDictionary元素中的,只不过不需要将ResourceDictionary元素显式的定义出来。如下所示:

<Window.Resources>
    <sys:Double x:Key="value">500</sys:Double>
</Window.Resources>

<!--其实WPF默认已经放入ResourceDictionary中了-->
<Window.Resources>
    <ResourceDictionary>
        <sys:Double x:Key="value">100</sys:Double>
    </ResourceDictionary>
</Window.Resources>

二、字典的合并

多个字典资源

资源字典常用在样式和模板上,那么不可避免的会出现一个XAML文件中需要引入多个资源字典的情况,而一个Resources元素中,只能含有一个ResourceDictionary子元素,此时就需要使用字典的合并了。

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/WPFResource;component/ButtonRes.xaml"/>
            <ResourceDictionary Source="pack://application:,,,/WPFResource;component/ButtonRes2.xaml"/>
        ResourceDictionary.MergedDictionaries>
    ResourceDictionary>
Window.Resources>

需要注意的是,如果引入的字典中出现了名字相同的资源,那么以最后引入的资源字典为准。

此外,使用合并字典后,TreeViewItemsControl等子项控件,可能会出现列表中的第一个数据不会加载字典中的样式,此时将样式抽取出来放在对应控件下的资源下即可,例如元素或下。

字典资源与自定义资源共存

在引入字典资源时,除了会引入多个字典资源外,有时还需要字典资源和自定义资源共存,这时也需要使用到字典合并,并且自定义资源必须显式的放在ResourceDictionary元素内。

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Assets;component/Styles/ButtonStyles.xaml"/>
            <ResourceDictionary>
                <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter"/>
                <Style x:Key="PasswordBoxStyle" TargetType="{x:Type PasswordBox}">......Style>
                <Style TargetType="Hyperlink"> ...... Style>
            ResourceDictionary>
        ResourceDictionary.MergedDictionaries>
    ResourceDictionary>
Window.Resources>

啰嗦的解释一下为什么这里要使用合并资源字典,原因很简单,哪怕只是引用了一个外部的资源字典,想要直接进行自定义资源是会报错的,上文说了我们自定义的资源WPF会自动放在ResourceDictionary中,也就相当于此时同时出现了两个资源字典,而一个Resources元素中,只能含有一个ResourceDictionary子元素,因此需要使用合并资源字典。

<Window.Resources>
    <ResourceDictionary Source="/Assets;component/Styles/ButtonStyles.xaml"/>
    
    <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter"/>
Window.Resources>

三、资源字典的动态修改

在xaml文件中加载资源字典后,有时候需要在运行中跟据用户的交互来进行资源字典的动态修改,此时可以通过如下C#代码来进行xaml文件上资源字典的修改。

资源字典联合情况下

private void buttonOne_Click(object sender, RoutedEventArgs e)
{
		//resDic为字典联合情境下,父类ResourceDictionary的实例名称
    resDic.MergedDictionaries.ToList()[0].Source = new Uri("pack://application:,,,/WPFResource;component/ButtonRes2.xaml");
}

单个资源字典情况下

private void buttonOne_Click(object sender, RoutedEventArgs e)
{
		//buttonRes为ResourceDictionary的实例名称
    buttonRes.Source = new Uri("pack://application:,,,/WPFResource;component/ButtonRes2.xaml");
}

通过Application实例进行资源字典的切换

可以通过当前应用的实例对象进行资源字典的切换:

var uri_cn = new Uri("pack://application:,,,/MultiLanguage;component/cn.xaml");
var uri_en = new Uri("pack://application:,,,/MultiLanguage;component/en.xaml");
var re = Application.Current.Resources.MergedDictionaries.Where(r => r.Source == uri_cn).FirstOrDefault();
Application.Current.Resources.MergedDictionaries.Remove(re);
ResourceDictionary re_en = new ResourceDictionary() { Source = uri_en};
Application.Current.Resources.MergedDictionaries.Add(re_en);

四、FindResource

当资源字典被引入到应用中后(局部xaml引入或全局App.xaml中引入),可以在代码中通过FindResource方法根据输入的key获取到对应的资源对象。

定义资源字典

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Image x:Key="MyIcon" Source="/Icons/bitbug_favicon.ico" x:Shared="false"/>
ResourceDictionary>

引入资源

<Window ......>
    <Window.Resources>
        <ResourceDictionary Source="Icons.xaml"/>
    Window.Resources>
    ......
Window>

代码中获取(或创建)资源对象

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var img = FindResource("MyIcon");
    }
}

样式定义


在WPF中,针对控件的样式提供了更加便捷的资源用法,即使用样式元素