WPF跨程序集共享样式(跨程序集隔离样式和代码)

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF跨程序集共享样式(跨程序集隔离样式和代码)相关的知识,希望对你有一定的参考价值。

原文:WPF跨程序集共享样式(跨程序集隔离样式和代码)

前记:WPF中的样式使用一般分为两种Statci和Dynamic.两者的区别可以理解为,前者在运行的时候已经确定了样式的风格,而后者可以根据资源在运行时的修改而修改也可以使用那些在运行时才存在的资源。

背景:有时候我们会将样式的资源和XAML页面代码分离,有时候也希望同一个资源可以在多个Application中使用;另外还有一个更致命的问题,如果我们在很多地方都写了重复的样式,突然有一天我们要修改,那岂不是要一个一个地方进行修改,那工作量实在不敢想象。好在WPF中提供了解决这个问题的好方法,那就是ComponentResourceKey(定义或引用基于外部程序集中的类名以及一个附加标识符的资源键。),也就是说我们可以指定一个统一的Key(并不是我们之前使用的),来绑定同一个资源。

发功(此功一共分为3步)

1.定义一个ComponentResourceKey需要的类型,如下:

    public class CustomResources
    {
        public static ComponentResourceKey DesertBrushKey
        {
            get
            {
                return new ComponentResourceKey(
                typeof(CustomResources), "DesertBrush");
            }
        }
    }

类名随意,其实类中可以没有东西,我们的内容稍后解释。

2.添加generic.xaml文件(如果你有可以忽略)、添加资源(直接写Dictionary字典或者直接写在generic.xaml中)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                      xmlns:local="clr-namespace:WpfApplication9">
    <ImageBrush 
        x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:CustomResources},ResourceId=DesertBrush}"
        ImageSource="/WpfApplication9;component/Desert.jpg"></ImageBrush>
</ResourceDictionary>

添加对命名空间的引用,然后写一个ImageBrush样式资源。关键来了,Key不是一个字符串,而是一个很复杂的不知道什么东东的东东。
解释: 关于Key设置的语法,往下看,在这里我们使用的是详细版的语法,ComponentResourceKey固定关键字,TypeInTargetAssembly即为我们创建的类型(x:Type为WPF提供的),ResourceID就是之前我们习惯设置的Key(名称随意)。

XAML设置键,精简版:

<object x:Key="{ComponentResourceKey {x:Type targetTypeName}, targetID}" .../>

XAML设置键,详细版:

<object x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type targetTypeName}, ResourceID=targetID}" .../>

请求资源,精简版:

<object property="{DynamicResource {ComponentResourceKey {x:Type targetTypeName}, targetID}}" .../>

请求资源,详细版:

<object property="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type targetTypeName}, ResourceID=targetID}}" .../>

 注意:generic.xaml路径为Themes/generic.xaml

3.使用资源

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:res="clr-namespace:WpfApplication9;assembly=WpfApplication9"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Background="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type res:CustomResources}, ResourceId=DesertBrush}}"></Button>
    </Grid>
</Window>

上述XAML文件和资源不在同一个程序,所以首先添加对上一个程序的引用,然后在XAML中添加对命名空间的引用,然后在Button的Background上使用我们的资源。
解释:资源的使用语法见上文,ComponentResoruceKey固定关键字,TypeInTargetAssembly也是我们创建的类,最后ResourceId同样为我们在资源中定义的ResourceId。


说在最后:其实本文还没完,还有很有用的一点,是不是觉得使用方式很复杂,是不是觉得类中的代码到底是干嘛的呢,开始解答。
鉴于使用资源的方法过于繁琐,可以在类中添加一个静态的属性类型同样为ComponentResoruceKey,返回值为实例化的ComponentResoruceKey,第一个参数为我们的类的类型,第二个参数为资源中的ResourceId的值,然后你就可以这么使用:

    <Button Background="{DynamicResource {x:Static  res:CustomResources.DesertBrushKey}}"></Button>

原谅我在最后才拿出简单的使用方法,我也是为大家好呢。







以上是关于WPF跨程序集共享样式(跨程序集隔离样式和代码)的主要内容,如果未能解决你的问题,请参考以下文章

正确支持WPF的混淆器

沙盒 AppDomain 跨程序集异常处理

Qt 跨应用程序样式问题

第二十一章 命名空间和程序集

Type.GetType()在跨程序集反射时返回null的解决方法

2021-09-12 WPF上位机 06-资源字典与样式