c#中PropertyGrid控件联合TypeConverter进行数据转换

本文介绍了.NETFramework中的TypeConverter类如何在WindowsForms开发、数据绑定、配置文件处理和序列化/反序列化中实现灵活的类型转换。作者针对Htuple数据类型转换的特殊需求,展示了如何使用自定义TypeConverter解决在C#开发中遇到的问题,以及在PropertyGrid控件中的应用和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:背景介绍

        TypeConverter 类是.NET Framework 中的一个重要组件,用于在不同类型之间进行转换。它位于System.ComponentModel命名空间中,是.NET框架中的类型转换机制的核心之一。

        在软件开发中,经常需要处理不同类型之间的转换,比如将字符串转换为整数、将对象转换为字符串等。TypeConverter 类的出现正是为了解决这类问题。它提供了一种灵活的机制,允许开发人员自定义类型之间的转换规则,从而实现更加灵活和可扩展的类型转换功能。

适用场景:

  1. Windows Forms 开发: 在 Windows Forms 应用程序中,TypeConverter 类常用于属性窗格(PropertyGrid)的实现中。通过为自定义对象提供自定义的 TypeConverter,可以让属性窗格正确地显示和编辑对象的属性,提高用户体验。

  2. 数据绑定: 在数据绑定的场景中,TypeConverter 用于将数据从一种类型转换为另一种类型,以便正确地绑定到用户界面控件上。通过为数据模型的属性提供合适的 TypeConverter,可以实现数据在界面上的正确展示和编辑。

  3. 配置文件处理: 在处理配置文件或者用户设置时,TypeConverter 可以帮助将配置数据从字符串形式转换为实际的对象类型。这样可以简化配置文件的处理,并提供更加友好的配置方式。

  4. 序列化与反序列化: 在对象的序列化与反序列化过程中,TypeConverter 也扮演着重要的角色。它可以帮助将对象转换为字符串形式进行序列化,或者从字符串形式反序列化为对象,从而实现对象的持久化存储和恢复。

二:开发过程中遇到的问题

          在c#联合halcon开发中我经常需要操作Halcon的一个数据类型Htuple。

        但是在开发过程中不停的对Htuple进行手动书写代码我觉得真是太麻烦了,你需要不停的

Htuple ht;然后ht.D,ht.L,ht.I 等操作这样会很麻烦的,想想都觉得头疼

        那么有没有一种办法就是这样一个场景,我需要进行数据类型的转换,但是我在一个类中定义的一个属性的数据类型,我需要转换成各种情况下我真实的需要的数据类型呢?

        答案是有的,使用微软中提供的TypeConverter进行数据转换,但是可以看到在网络上大部分进行数据转换只能够转为一种,适应性,可扩展性,都不能够满足人们的需求。

        看下面这段代码。        

        //重要参数创建模型的模型ID
        private HTuple _modelID;
        [Browsable(true),
            Category("输出:模型参数设置"), 
            DisplayName("模板ID"), 
            Description("创建模板生成的模板ID")
             , TypeConverter(typeof(HTupleTypeConverter<int>))
             ]
        public HTuple ModelID
        {
            get { return _modelID; }
            set
            {
                _modelID = value;
                OnPropertyChanged("ModelID");
            }
        }

        我们可以观察到我希望的是直接对属性定义为Htuple类型,然后通过特性的方式直接转为我任何期望的数据类型。c#中的int,float,double,string等。

三:对PropertyGrid控件的使用进行一个汇总。

        顾名思义,叫做属性网格控件

        通过PropertyGrid中的SelectObj进行对象绑定,例如

propG_参数设置.SelectedObject = modelMatching.modelParemeter;

通过这段代码就可以完成实体类中的属性和属性网格控件(PropertyGrid)进行的一种映射,

常用特性:我简要写一下,网上有很多讲解的不过多赘述

     //重要参数创建模型的模型ID
     private HTuple _modelID;
     [Browsable(true),
         Category("输出:模型参数设置"), 
         DisplayName("模板ID"), 
         Description("创建模板生成的模板ID")
          , TypeConverter(typeof(HTupleTypeConverter<int>))
          ]

        Browsable:当前属性在外部是否可见,一般不见也可以默认的就是true,允许可见的

        Category:网格中多个属性的时候需要对网格中的属性进行归类,假设:写上输入

那么属于输入的就在哪里排列着,输出也一样。

        

其实相当于Halcon中的输入与输出对不同的属性进行了一个归类。(我说的是大白话,需要定义的可以查找网上其他资源)

        DisplayName:就是在属性网格空间中每个属性对应的名字:例如这里的margin,Tag等

        Description:对每一个属性的描述,看到了吗就是下面这种的说明

个人认为有这4个特性就可以了。

四:对上述第二个问题解决方案的源码

    public class HTupleTypeConverter<T> : TypeConverter
    {
        // 指示是否可以将值转换为指定的目标类型
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
                return true;
        }

        /// <summary>
        /// 当用户在后端代码改变的时候执行这里
        /// HTuple 类型的值转换为其他类型,以满足不同的显示或存储需求。
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <param name="destinationType"></param>
        /// <returns></returns>
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (value is HTuple)
            {
                //如果当前的value类型是Htuple类型那么
                string str = value.ToString();
                var value1=  ConvertFromString(str);
                return base.ConvertTo(context, culture, value1, destinationType);
            }
            if (destinationType == typeof(string) && value is T)
            {
                T val = (T)value;
                // 根据泛型类型 T 将 val 转换为字符串
                return val.ToString();
            }
            else if (destinationType == typeof(HTuple) && value is T)
            {
                T val = (T)value;
                // 根据泛型类型 T 转换为 HTuple
                // 这里需要你根据实际情况来实现转换
                HTuple convertedValue = ConvertToHTuple(val);
                return convertedValue;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }

        // 指示是否可以将从字符串转换的值分配给对象
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string) || sourceType == typeof(T))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }

        /// <summary>
        /// 当用户手动在控件中输入数据的时候会执行这里的代码
        ///外部数据源将数据转换为 HTuple 类型
        /// </summary>
        /// <param name="context"></param>
        /// <param name="culture"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string)
            {
                // 根据字符串创建泛型类型 T 对象
                string stringValue = (string)value;
                // 根据泛型类型 T 创建对应类型的对象
                T convertedValue = ConvertFromString(stringValue);
                if (convertedValue is T)
                {
                    // 将泛型类型 T 转换为 HTuple
                    // 这里需要你根据实际情况来实现转换
                    HTuple toHtuple = ConvertToHTuple(convertedValue);
                    return toHtuple;
                }
            }
            else if (value is T)
            {
                // 将泛型类型 T 转换为 HTuple
                T val = (T)value;
                // 这里需要你根据实际情况来实现转换
                HTuple convertedValue = ConvertToHTuple(val);
                return convertedValue;
            }
            return base.ConvertFrom(context, culture, value);
        }

        // 根据泛型类型 T 将其转换为 HTuple
        private HTuple ConvertToHTuple(T value)
        {
            // 这里需要你根据实际情况来实现转换
            // 这里仅作为示例,你需要根据实际情况来实现转换
            // 示例中将 T 类型的值转换为 HTuple 类型
            return new HTuple(value);
        }

        // 根据字符串创建泛型类型 T 对象
        private T ConvertFromString(string value)
        {
           //获取当前属性需要转为的转换为的数据类型
            Type aType = typeof(T);

           object obj=Convert.ChangeType(value, typeof(T));
            return (T)obj;
        }
    }

可以观察到有两个重要的重写TypeConveter的方法一个是 ConvertTo和ConvertFrom,

        我用大白话的形式像大家解释这两个方法的区别。

         ConvertTo就是当你手动在后端,对当前属性进行赋值的时候,想要刷新到绑定到PropertyGrid控件的时候执行这里(注意:为什么需要这样转换,因为PropertyGrid控件不认识你定义的Htuple类型,所以你在后端每次赋值的时候都需要转为c#的数据类型

        假如你不把Htuple转为PropertyGrid控件可以接受的数据类型,显然最后(可能在PropertyGrid控件中可能不会显示属性,或者也不会更改属性)

        ConvertFrom就是当你更改PropertyGrid控件中的代码的时候,会从UI层,转为当前你定义的Htuple数据类型(注意:我的初衷就是不要对Htuple进行数据转换,通过这样我就可以做到了)

        显然这个泛型类是可以改变的不单是从Htuple转为泛型数据类型T。

        private HTuple ConvertToHTuple(T value)
        {
            // 这里需要你根据实际情况来实现转换
            // 这里仅作为示例,你需要根据实际情况来实现转换
            // 示例中将 T 类型的值转换为 HTuple 类型
            return new HTuple(value);
        }

你可以修改这里的逻辑代码,当PropertyGrid控件(UI层更改数据后)转换为实际的当前属性的数据类型。大家可以根据自己的需求来改变。(提供一个思路:假如当前属性的数据类型不是任何的c#数据类型是你定义的类的情况下,你是不是就需要这样来改写了。

五:在PropertyGrid控件中对数据更新的问题。

        前提:你需要用TypeConverter进行数据转换,必须要测试一下,ConvertTo,ConvetFrom这两个重写的方法,要保证当后端变换到UI(ConvertTo方法可以执行,可以到达你预想的数据类型),UI到后端属性(ConvetFrom方法也可以转换为你自己当前定义的属性的数据类型)。

         前提不出错,当你调用下面的Refresh()方法才不会出现错误,不然你肯定会遇到一些错误:

                1:需要手动点击PropertyGrid控件中的属性,才会显示数据

                2:转换错误后:在propertygrid控件中是空白

        当你后端代码变化后,你想让PropertyGrid中的数据也显示变化,应该怎么办呢,答案是

调用ProPertyGrid控件中的。控件.Refresh()方法来刷新数据,这样就可以刷新到网格属性控件上供用户使用了。

六:结束

        在本文中,我们深入了解了微软中的 C# 中的 TypeConverter 类以及PropertyGrid控件,它作为 .NET Framework 中的重要组件,在不同类型之间的转换中发挥着关键作用。通过灵活的机制,TypeConverter 类使得类型转换更加容易和可扩展,为开发人员提供了丰富的选择和解决方案。

        不论是在 Windows Forms 开发中,数据绑定,配置文件处理,还是序列化与反序列化过程中,TypeConverter 类都能展现其强大的功能和应用价值。它不仅简化了开发工作,提高了开发效率,还提升了用户体验,使得软件更加灵活和易于维护。

        在未来的软件开发中,我们可以继续深入研究和应用 TypeConverter 类,发掘其更多的潜力,为构建高效、可靠的软件系统做出更大的贡献。

        如有错误,希望大家指证,博主愿意和大家一起学习,一起进步,觉得不错的希望您能关注博主,我将持续分享开发中遇到的问题。

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SmallTown2

您的打赏,是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值