【wpf】枚举的绑定最易用法 和 全局静态绑定的应用

news2024/11/19 17:41:27

背景

        有时我们做配置界面的时候,有很多配置项是枚举。通过我们会用一个Combobox实现,如果能直接用Combobox绑定枚举,那将会非常方便。这里绑定将涉及到两个方面,一个是数据源的绑定,还有就是当前选择项的绑定。最后我们要将选择项的信息进行保存,下次打开的时候就刚好是我们上次选择的项。

枚举数据源的绑定

        要想直接绑定枚举作为源,我们得首先准备一个类,这里我直接给出源代码,内容可以先不用理解。

 public class EnumBindingSourceExtension : MarkupExtension
    {
        private Type _enumType;

        public Type EnumType
        {
            get { return _enumType; }
            set
            {
                if (value != _enumType)
                {
                    if (null != value)
                    {
                        var enumType = Nullable.GetUnderlyingType(value) ?? value;
                        if (!enumType.IsEnum)
                        {
                            throw new ArgumentException("Type must bu for an Enum");
                        }

                    }

                    _enumType = value;
                }
            }
        }

        public EnumBindingSourceExtension()
        {

        }

        public EnumBindingSourceExtension(Type enumType)
        {
            EnumType = enumType;
        }
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (null == _enumType)
            {
                throw new InvalidOperationException("The EnumTYpe must be specified.");
            }

            var actualEnumType = Nullable.GetUnderlyingType(_enumType) ?? _enumType;
            var enumValues = Enum.GetValues(actualEnumType);

            if (actualEnumType == _enumType)
            {
                return enumValues;
            }

            var tempArray = Array.CreateInstance(actualEnumType, enumValues.Length + 1);
            enumValues.CopyTo(tempArray, 1);

            return tempArray;
        }
    }

然后在前台引用这个类,并且指点你声明得枚举类型即可:

这里有个小疑惑,就是我声明的类叫做EnumBindingSourceExtension,但是这里绑定的时候却可以写成(EnumBindingSource),也就是Extension 可以省略。所以不管你是否带上Extension 绑定都是工作的。

<ComboBox 
ItemsSource="{Binding Source={tools:EnumBindingSource {x:Type vm:MaskDetection}}}"/>

此时你就会发现已经绑定成功了!就是这么简单!

 枚举选择项的绑定

<ComboBox 
SelectedValue="{Binding saveInfo.enumMaskDetection, Source={x:Static md:GlobalData.Instance}}"

ItemsSource="{Binding Source={tools:EnumBindingSource {x:Type vm:MaskDetection}}}"/>

注意这里一定要使用SelectedValue,而不是 SelectedItem。至于:

saveInfo.enumMaskDetection, Source={x:Static md:GlobalData.Instance}

这句话其实是静态绑定的语法。  因为这些选择项作为配置,都是需要保存的,所以实现了一个单例模式的全局类(GlobalData)以及信息类(SaveInfo ),专门用于保存全局变量。

全局静态绑定

构建保存数据类

首先我构造一个信息类,这里面都声明的是枚举变量

public class SaveInfo 
    {

        public ColorSpace enumColorSpace { get; set; }
        public Illuminant enumIlluminant { get; set; }
        public Observer enumObserver { get; set; }

        public MeasurementMethod enumMeasurementMethod { get; set; }
        public MeasurementArea enumMeasurementArea { get; set; }
        public SpecularComponent enumSpecularComponent { get; set; }
        public MaskDetection enumMaskDetection { get; set; }

    }

和界面的中的选择项是一一对应的: 

最终这些选项选择的内容都会保存到该类中。

构建全局类

public class GlobalData
{
    /// <summary>
    /// 单例模式
    /// </summary>
    public static GlobalData Instance { private set; get; } = new GlobalData();

    public SaveInfo saveInfo { get; set; }

    private GlobalData()
    {
        var a = JsonConfigCtrl.Read<SaveInfo>("GlobalData");
        if (a == null)
        {
            saveInfo = new SaveInfo();
        }
        else
        {
            saveInfo = a;
        }
    }

    public void Save()
    {
        JsonConfigCtrl.Save<SaveInfo>(saveInfo, "GlobalData");
    }
}

序列化和反序列化

这里,要说明的是这个GlobalData是一个单例模式的类,注意他的构造函数是私有类型(确保了单例)。但是这会导致一个问题,就是无法序列化,因为序列要求有一个public的无参构造函数!

其实直接序列化GlobalData也不好,所以我用单独建立了SaveInfo 类,然后将SaveInfo 类作为他的成员对象!

然后在构造GlobalData时候,反序列化SaveInfo,由于做了静态绑定,所以反序列化SaveInfo后,界面会跟着配置改变。(这里注意,首次的数据到界面的同步,绑定是不需要通知函数的!而界面到数据同步是绑定默认的)。

在save里,我们继续序列化操作,将当前界面的数据保存到本地。

后台使用配置变量

由于直接绑定的就是枚举类型,所以无需转换直接赋值就好了!!!

setCalcCondition.ColorSpace = GlobalData.Instance.saveInfo.enumColorSpace;
setCalcCondition.Illuminant = GlobalData.Instance.saveInfo.enumIlluminant;
setCalcCondition.Observer = GlobalData.Instance.saveInfo.enumObserver;

小结

        通过这种方式绑定枚举、配置参数的使用,以及序列化和反序列化,真的是超级方便。

附录

序列化的相关代码

namespace ColorTest.Tools
{
    public class JsonConfigCtrl
    {
        static JsonSerializerOptions options;

        static JsonConfigCtrl()
        {
            options = new JsonSerializerOptions();
            options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All);
        }

        /// <summary>
        /// 序列化操作  
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        static public void Save<T>(T obj, string filename = "config")
        {
            string _filePath = Directory.GetCurrentDirectory() + $"\\Config\\{filename}.json";
            FileInfo fi = new FileInfo(_filePath);
            if (!Directory.Exists(fi.DirectoryName))
            {
                Directory.CreateDirectory(fi.DirectoryName);
            }


            //StreamWriter yamlWriter = File.CreateText(_filePath);


            string str = System.Text.Json.JsonSerializer.Serialize(obj, options);
            str = JsonHelper.FormatJson(str);
            File.WriteAllText(_filePath, str);



            //Serializer yamlSerializer = new Serializer();
            //yamlSerializer.Serialize(yamlWriter, obj);
            //yamlWriter.Close();
        }

        /// <summary>
        /// 泛型反序列化操作  
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="FileNotFoundException"></exception>
        static public T Read<T>(string filename = "config") where T : class, new()
        {
            string _filePath = Directory.GetCurrentDirectory() + $"\\Config\\{filename}.json";
            if (!File.Exists(_filePath))
            {
                return default;
            }


            //读取持久化对象  
            try
            {
                T info = JsonSerializer.Deserialize<T>(File.ReadAllText(_filePath));

                return info;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return default;
            }
        }
    }


    public class JsonHelper
    {
        private const string INDENT_STRING = "    ";
        public static string FormatJson(string str)
        {
            var indent = 0;
            var quoted = false;
            var sb = new StringBuilder();
            for (var i = 0; i < str.Length; i++)
            {
                var ch = str[i];
                switch (ch)
                {
                    case '{':
                    case '[':
                        sb.Append(ch);
                        if (!quoted)
                        {
                            sb.AppendLine();
                            Enumerable.Range(0, ++indent).MyForEach(item => sb.Append(INDENT_STRING));
                        }
                        break;
                    case '}':
                    case ']':
                        if (!quoted)
                        {
                            sb.AppendLine();
                            Enumerable.Range(0, --indent).MyForEach(item => sb.Append(INDENT_STRING));
                        }
                        sb.Append(ch);
                        break;
                    case '"':
                        sb.Append(ch);
                        bool escaped = false;
                        var index = i;
                        while (index > 0 && str[--index] == '\\')
                            escaped = !escaped;
                        if (!escaped)
                            quoted = !quoted;
                        break;
                    case ',':
                        sb.Append(ch);
                        if (!quoted)
                        {
                            sb.AppendLine();
                            Enumerable.Range(0, indent).MyForEach(item => sb.Append(INDENT_STRING));
                        }
                        break;
                    case ':':
                        sb.Append(ch);
                        if (!quoted)
                            sb.Append(" ");
                        break;
                    default:
                        sb.Append(ch);
                        break;
                }
            }
            return sb.ToString();
        }



    }

    static class Extensions
    {
        public static void MyForEach<T>(this IEnumerable<T> ie, Action<T> action)
        {
            foreach (var i in ie)
            {
                action(i);
            }
        }
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495830.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每天一道算法练习题--Day23 第一章 --算法专题 --- ----------并查集

背景 相信大家都玩过下面的迷宫游戏。你的目标是从地图的某一个角落移动到地图的出口。规则很简单&#xff0c;仅仅你不能穿过墙。 实际上&#xff0c;这道题并不能够使用并查集来解决。 不过如果我将规则变成&#xff0c;“是否存在一条从入口到出口的路径”&#xff0c;那么…

DDR5内存彻底白菜价,国外大厂却整出了比着火更离谱的骚操作

今年的 PC 硬件市场&#xff0c;似乎出现了明显两极分化现象。 一边是 N、A 两家新显卡价格高高在上&#xff0c;摆明了不坑穷人。 另一边固态硬盘、内存条又在疯狂互卷不断杀价。 四五百元的 2TB SSD&#xff0c;二百元的 16G 内存条早已见怪不怪。 要说面世多年的 PCIe 3.0…

对比 LVS 负载均衡群集的 NAT 模式和 DR 模式,基于 CentOS 7 构建 LVS-DR 群集

1. 对比 LVS 负载均衡群集的 NAT 模式和 DR 模式&#xff0c;比较其各自的优势 。 LVS&#xff08;Linux Virtual Server&#xff09;是一个开源的负载均衡软件&#xff0c;它支持多种负载均衡算法&#xff0c;包括 NAT 模式和 DR &#xff08;Direct Routing&#xff09;模式…

【数据分析之道-Matplotlib(二)】Matplotlib 绘图标记

文章目录 专栏导读1、前言2、标记&#xff08;Markers&#xff09;2.1关键词参数marker2.2标记参考&#xff08;Marker Reference&#xff09; 3、Format Strings fmt3.1fmt参数3.2线参考&#xff08;Line Reference&#xff09; 4、标记颜色(Marker Color)4.1关键字参数mec4.2…

《程序员面试金典(第6版)》面试题 16.14. 最佳直线(向量,C++)

题目描述 给定一个二维平面及平面上的 N 个点列表Points&#xff0c;其中第i个点的坐标为Points[i][Xi,Yi]。请找出一条直线&#xff0c;其通过的点的数目最多。 设穿过最多点的直线所穿过的全部点编号从小到大排序的列表为S&#xff0c;你仅需返回[S[0],S[1]]作为答案&#xf…

简述对象检测与图像分类与关键点检测区别

计算机视觉是人工智能的一个多元化领域&#xff0c;旨在检测和识别图像或视频的内容。大多数开始计算机视觉领域之旅的人的常见问题之一是&#xff1a;目标检测、图像分类和关键点检测之间有什么区别&#xff1f; 让我们先看看 什么是对象检测 对象检测是一种计算机视觉和图像…

gateway sentinel 流控规则持久化到 nacos

Sentinel改造 sentinel版本是1.8.6 直接看更新内容, 右侧更新后 GatewayApiController /*** Gateway api Controller for manage gateway api definitions.** author cdfive* since 1.7.0*/ RestController RequestMapping(value "/gateway/api") public class…

【操作系统】内存空间

最小的操作系统Hello world 想要pmap这个进程&#xff0c;需要进程号 但是这个进程在启动的一瞬间就执行完了 用GDB把程序暂停下来&#xff0c;然后用pmap观察地址空间 用info inferiors得到gdb里的进程号 ro 可读 &#xff1a;只读数据 rx 可读可执行 &#xff1a;代码 rw 可…

Java学习:Scanner类及其应用

Java Scanner 一、next()二、nextLine()三、应用 一、next() 用于从标准输入读取下一个字符串。该方法会扫描输入流并返回下一个非空白字符序列&#xff0c;以空格、制表符或换行符作为分隔符 1、next()会以空格作为分隔符,一行输入1 2 3,只会打印出1 import java.util.Scan…

Java RSA密钥转换,从RSAPrivateKey得到RSAPublicKey

概述&#xff1a; 在Java编程中&#xff0c;我们经常用到如下一段代码来生成RSA公私钥&#xff0c;分别拿到公私钥然后加解密计算&#xff1a; KeyPairGenerator keyPairGen; keyPairGen KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048, new S…

Oracle Instant Client + PLSQL 部署终端PC远程连接数据库服务器简易操作

系统环境&#xff1a; 1、win7_64bit 2、instantclient_21_10 3、plsqldev1105_x64 4、远程Oracle数据库&#xff1a;Oracle11g R2 操作步骤&#xff1a; 1、下载好Oracle Instant Client 和PLSQL程序安装包&#xff1a; 1.1 Oracle Instant Client 官网&#xff1a;https://w…

MySQL基础(五)排序与分页

1. 排序数据 1.1 排序规则 使用 ORDER BY 子句排序 ASC&#xff08;ascend&#xff09;: 升序DESC&#xff08;descend&#xff09;:降序 ORDER BY 子句在SELECT语句的结尾。 1.2 单列排序 SELECT last_name, job_id, department_id, hire_date FROM employees ORDER…

Redis之三大特殊数据类型:Geospatial:地理位置 hyperloglog:实现的功能是计算统计 bitmaps:位存储

三大特殊数据类型结构&#xff0c;十分的少见但是开源项目中依然有它们的身影 Geospatial:地理位置 实现的功能&#xff1a;附近的人&#xff0c;城市与城市之前的距离计算 添加城市经纬度到key中&#xff0c;经纬度则是key的value值&#xff0c;在正常的开发过程中&#xf…

获得 随机验证码(以图片为底层)

1&#xff1a;工具类 Slf4j public class RandomValidateCode {private static String baseNumLetter "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";private static String font "微软雅黑";//绘制验证码图片,返回验证码文本内容pu…

【机器学习】pytorch安装——环境配置(极简教程)

&#x1f951; Welcome to Aedream同学 s blog! &#x1f951; 文章目录 省流总结新建环境确定显卡型号安装显卡驱动安装pytorch国内镜像下载本地下载 验证安装成功 最近重新配置环境&#xff0c;简单记录一下。最近chatgpt等大语言模型和ai绘图火热&#xff0c;也为了方便很多…

视频剪辑必备的6个免费素材网站

做视频剪辑需要用到视频、音频、图片等素材&#xff0c;推荐几个网站&#xff0c;有免费、有付费&#xff0c;可根据需求自信选择~赶紧收藏起来&#xff01; 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库可以找到设计、办公、图片、视频、音频等各种…

电视机顶盒哪个牌子好?数码小编盘点电视机顶盒排行榜

电视机顶盒哪个牌子好&#xff1f;这是困扰新手们的一大难题&#xff0c;部分产品被爆出虚标高配、偷工减料&#xff0c;面对众多的机顶盒品牌和型号&#xff0c;怎么选择才好&#xff1f;小编以销量和用户评价为标准&#xff0c;盘点了电视机顶盒排行榜&#xff0c;跟着我一起…

Web端3D轻量化引擎基于PBR渲染——仿真模拟更逼真

HOOPS Communicator在2021版本中&#xff0c;推出了基于PBR&#xff08;Physically Based Rendering&#xff09;的渲染特性以提供更高质量的渲染技术。 PBR将材料表示为一系列方程&#xff0c;这些方程对光如何从表面反射进行建模&#xff0c;再通过GPU上运行的着色器代码进行…

MySQL基础(二)MySQL环境搭建

. MySQL的卸载 步骤1&#xff1a;停止MySQL服务 在卸载之前&#xff0c;先停止MySQL8.0的服务。按键盘上的“Ctrl Alt Delete”组合键&#xff0c;打开“任务管理器”对话框&#xff0c;可以在“服务”列表找到“MySQL8.0”的服务&#xff0c;如果现在“正在运行”状态&…

linux:命令grep查找关键字、wc统计以及管道符

linux:命令grep查找关键字、wc统计以及管道符 grep: wc: 输入wc test.txt时&#xff0c;输出了2 11 59 这三个数字 意思是:2行、11个单词(用空格分开就算一个单词)、59个字符(字节) ls -l看了看&#xff0c;也确实是59个字节。 通过wc的可选项来进行查看&#xff1a; 管道符…