WPF之Resource

Resource

WPF资源系统是一种保管一系列有用对象(如常用的画刷、样式或模板)的简单方法,从而使您可以更容易地重用这些对象。

注:不要将WPF对象资源与程序集资源混为一谈。程序集资源是一块嵌入到编译过的程序集中的二进制数据。使用程序集资源可以确保应用程序具有其所需的图像或声音文件。另一方面,对象资源是希望在某个位置定义并在其他几个位置重复使用的.NET对象。

1、资源基础

WPF允许在代码中以及在标记中的各个位置定义资源(和特定的控件、窗口一起定义,或在整个应用程序中定义)。

  • 高效,可重复使用,精简代码,更加高效
  • 可维护,在Xaml中创建资源相当于在代码中创建常量
  • 适应性强

1.1、资源集合

每个元素都有Resourcess属性,该属性存储了一个资源字典集合(它是ResourceDictionary类的实例)。资源集合可包含任意类型的对象,并根据字符串编写索引。

<Window.Resources>
    <ImageBrush x:Key="TileBrush" TileMode="Tile"
                ViewportUnits="Absolute" Viewport="0 0 32 32"
                ImageSource="happyface.jpg" Opacity="0.3">
    </ImageBrush>
</Window.Resources>

使用该资源:动态和静态

使用静态资源是,必须总是在引用资源之前的标记中定义资源。

<Button Background="{StaticResource TileBrush}">A Tiled Button</Button>
<Button Background="{DynamicResource TileBrush}">A Tiled Button</Button>

1.2、资源的层次

元素会先从自己的资源集合中开始查找指定的资源名。所以对于两个同名的资源,如果在子元素中定义了与父级元素同样的名称的资源是允许的,并且子元素会优先使用自己的资源。

1.3、静态资源和动态资源

StaticResource和DynamicResource有什么区别?

区别在于静态资源只从资源集合中获取对象一次。根据对象的类型(以及使用对象的方式),对象的任何变化都可能被立即注意到。然而,动态资源在每次需要对象时都会重新从资源集合中查找对象。这意味着可以在同一键下放置一个全新的对象,而且动态资源会应用该变化。

this.Resource["TileBrush"] = new SolidColorBrush(Color.LightBlue);

动态资源会应用该变化,而静态资源不知道它的画刷已在Resources集合中被其他内容替换了,它仍然继续使用原来的ImageBrush。

一般情况下,不需要使用动态属性,因为比较消耗性能,在下面的情况里需要使用DynamicResource

  • 资源具有依赖于系统设置的属性(如当前Windows操作系统的颜色或字体)
  • 准备通过编程方式替换资源对象(例如,实现几类动态皮肤特性)

1.4、通过代码访问资源

可以使用FrameworkElement.FindResource()方法以相同的方式查找资源,下面的代码是一个示例

private void cmd_Click(object sender, RoutedEventArgs e)
{
    Button cmd = (Button)sender;
    ImageBrush brush = (ImageBrush)cmd.FindResource("TileBrush");
}

1.5、应用程序资源

窗口不是查找资源的最后一站。如果在控件或其容器中(直到包含窗口或页面)找不到指定的资源,WPF会继续检查为应用程序定义的资源集合。在VS中,这些资源是在App.xaml文件的标记中定义的资源。

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ImageBrush x:Key="TileBrush" TileMode="Tile"
                    ViewportUnits="Absolute" Viewport="0 0 32 32"
                    ImageSource="happyface.jpg" Opacity="0.3">
        </ImageBrush>
    </Application.Resources>
</Application>

当某个元素查找资源时,应用程序资源仍然不是最后一站。如果没有在应用程序资源中找到所需的资源,元素还会继续查找系统资源。

1.6、资源字典

<Application x:Class="StoryEditor.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             Startup="Application_Startup" 
             DispatcherUnhandledException="Application_DispatcherUnhandledException">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries> 
                <ResourceDictionary Source="/Resource/String/zh-CN.xaml" />
                <ResourceDictionary Source="/Resource/TelerikLocalization/RadControl.zh-CN.xaml" />
                <ResourceDictionary Source="/Resource/Value/Dim.xaml" />
                <ResourceDictionary Source="/Resource/Value/Color.xaml" />
                <ResourceDictionary Source="/Resource/Value/Style.xaml" />
                <ResourceDictionary Source="/Resource/Value/Validation.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

在程序集中共享资源:切换主题的示例

public void ChangeTheme(string theme)
{
    if (String.IsNullOrEmpty(theme))
    {
        return;
    }

    List<string> requestedTheme = null;
    if (theme.Contains("dark"))
    {
        requestedTheme = new List<string>() {
            @"/Telerik.Windows.Themes.Green;component/Themes/Telerik.Windows.Controls.xaml" ,
        };
    }
    else if (theme.Contains("light"))
    {
        requestedTheme = new List<string>() {
            @"/Telerik.Windows.Themes.Office2016;component/Themes/Telerik.Windows.Controls.xaml" ,
        };
    }

    if (requestedTheme != null && requestedTheme.Count > 0)
    {
        RemoveAllThemeRes();
        foreach (var rc in requestedTheme)
        {
            Resources.MergedDictionaries.Add(
                new ResourceDictionary() { Source = new Uri(rc, UriKind.Relative) });
        }
        Settings.Default.Theme = theme;
        Settings.Default.Save();
    }
}
posted @ 2020-07-12 14:33  别问,问就不会  阅读(1173)  评论(0)    收藏  举报