前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WPF 在后台代码定义 ResourceDictionary 资源字典

WPF 在后台代码定义 ResourceDictionary 资源字典

作者头像
林德熙
发布2022-08-12 16:19:57
1.4K0
发布2022-08-12 16:19:57
举报
文章被收录于专栏:林德熙的博客

在 WPF 中的 ResourceDictionary 资源字典大部分都是在 XAML 里面定义的,但是在 C# 代码定义一个资源字典也是可行的,只是写起来有点诡异

在 CSharp 后台代码里面给 WPF 定义资源字典需要重新创建一个类,让这个类继承 ResourceDictionary 如以下代码

代码语言:javascript
复制
    public class Foo : ResourceDictionary
    {

    }

然后在构造函数里面加入测试的代码,添加一个颜色作为资源

代码语言:javascript
复制
    public class Foo : ResourceDictionary
    {
        public Foo()
        {
            Add("Foo", Brushes.Gray);
        }
    }

在后台代码添加的资源需要在被加入到使用之前,完成资源的添加,因此建议写在构造函数里面

使用这个在后台代码定义的资源字典有两个方法,一个是在 XAML 引用,另一个是在后台代码添加

在 XAML 引用的逻辑如下

代码语言:javascript
复制
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <local:Foo></local:Foo>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid Background="{StaticResource Foo}">

    </Grid>

需要注意的是在 C# 后台定义的 WPF 资源字典不能通过 Url 的方式引用,而是需要通过实例的方式。可以选择创建实例或引用资源的方式,如上面代码是创建实例

在上面代码定义了一个测试使用的代码,尝试使用 StaticResource Foo 静态资源,这个静态资源是定义在后台代码的资源字典的,运行代码可以看到能绑定上

而在后台代码添加引用的方法如下

代码语言:javascript
复制
    Resources.MergedDictionaries.Add(new Foo());

这就是在后台定义资源字典的用法了

在后台代码定义资源字典还有一个有趣的黑科技是重新返回资源的值

大概代码逻辑如下

代码语言:javascript
复制
    public class Foo : ResourceDictionary
    {
        public Foo()
        {
            Add("Foo", Brushes.Gray);
        }

        protected override void OnGettingValue(object key, ref object value, out bool canCache)
        {
            value = Brushes.Blue;
            canCache = true;
        }
    }

在这个资源字典里面定义了 Foo 是灰色,但是在 OnGettingValue 方法里面返回的是蓝色。因此在 XAML 里面绑定静态资源的时候,将会显示的实际颜色是蓝色

另外只要资源里面的值不是 null 空,那么都会进入 OnGettingValue 方法去读取实际返回的值,而实际返回值是 object 类型,意味着可以愉快更改返回类型

代码语言:javascript
复制
        public Foo()
        {
            Add("Foo", null); // 传入 null 将不会进入 OnGettingValue 方法
        }

        protected override void OnGettingValue(object key, ref object value, out bool canCache)
        {
            value = Brushes.Blue;
            canCache = true;
        }

如以下代码,传入的是 object 但是在 OnGettingValue 方法可以返回颜色

代码语言:javascript
复制
        public Foo()
        {
            Add("Foo", new object());
        }

        protected override void OnGettingValue(object key, ref object value, out bool canCache)
        {
            value = Brushes.Blue;
            canCache = true;
        }

利用这个有趣的科技也可以用来做多语言或者主题色等,只是这个方法没有自动的更新值机制

本文代码放在github欢迎小伙伴访问

而在 XAML 定义内容,同时支持对应的后台代码也可以,但是没有什么意义,至少我还不知道这个功能有什么作用

做法就是和上面代码一样,定义一个继承 ResourceDictionary 的类,如下面代码

代码语言:javascript
复制
    public class ResourceJainahijainenelHuceenukur : ResourceDictionary
    {
        public ResourceJainahijainenelHuceenukur()
        {
            Debugger.Break();
        }

        protected override void OnGettingValue(object key, ref object value, out bool canCache)
        {
            Debugger.Break();
            base.OnGettingValue(key, ref value, out canCache);
        }
    }

接着创建一个资源字典,创建之后修改 ResourceDictionary 为刚才创建的类名

代码语言:javascript
复制
 <local:ResourceJainahijainenelHuceenukur xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                           xmlns:local="clr-namespace:KemkicemdurFemceloja">
    <SolidColorBrush x:Key="Foo" Color="Aquamarine"></SolidColorBrush>
</local:ResourceJainahijainenelHuceenukur>

此时就完成了,依然使用的时候使用 url 的形式

但是这样做我想不到有多少意义,因为 OnGettingValue 方法尽管重写了,但是实际不会被调用进入

本文代码放在github欢迎小伙伴访问

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档