C# Winform PropertyGrid显示中文

news/2024/7/8 4:58:55 标签: c#, 开发语言

主要原理是在枚举上添加DescriptionAttribute属性,然后通过反射将其显示出来

方法1:继承StringConverter类

public class EnumConvertor : StringConverter
{
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (!(value is string)) return base.ConvertFrom(context, culture, value);
        var type = context.GetValue<Type>("PropertyType");
        var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static)
            .FirstOrDefault(f =>
            {
                if (!(f.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)) return false;
                return description.Description.Equals(value.ToString());
            });

        if (type != null && field != null)
            return Enum.Parse(type, field.Name);

        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        // 将Enum类型转换成string进行显示
        if (destinationType != typeof(string)) return base.ConvertTo(context, culture, value, destinationType);
        var type = context.GetValue<Type>("PropertyType");
        var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static)
            .FirstOrDefault(f => f.Name.Equals(value.ToString()));

        if (field != null && field.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)
            return description.Description;

        return base.ConvertTo(context, culture, value, destinationType);
    }

    public override StandardValuesCollection
        GetStandardValues(ITypeDescriptorContext context)
    {
        List<string> list = new List<string>();
        var type = context.GetValue<Type>("PropertyType");
        foreach (var info in type.GetFields(BindingFlags.Public | BindingFlags.Static))
        {
            if (!(info.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description))
                continue;
            list.Add(description.Description);
        }
        return new StandardValuesCollection(list);
    }
}

方法2:自定义界面显示

public class EnumEditor : UITypeEditor
{
    private class EnumItem
    {
        public object Value { get; set; }

        public string Name { get; set; }
    }

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }

    public override object EditValue(ITypeDescriptorContext context, 
        IServiceProvider provider, object value)
    {
        bool cancel;
        if (provider == null) return value;

        if (!(provider.GetService(typeof(IWindowsFormsEditorService)) is IWindowsFormsEditorService editorService))
            return value;
      
        ListBox listBox = new ListBox
        {
            DisplayMember = "Name",
            // 这里需要将DrawMode设置成OwnerDrawVariable才可以设置ItemHeight
            DrawMode = DrawMode.OwnerDrawVariable,
            //IntegralHeight = true,
            Font = provider.GetValue<PropertyGrid>("OwnerGrid").Font,
            SelectionMode = SelectionMode.One
        };

        listBox.DrawItem += (sender, args) =>
        {
            args.DrawBackground();
            args.DrawFocusRectangle();
            StringFormat strFmt = new StringFormat();
            // 文本水平居中
            // strFmt.Alignment = StringAlignment.Center;
            // 文本垂直居中(根据需求进行设置)
            strFmt.LineAlignment = StringAlignment.Center; 
            args.Graphics.DrawString((listBox.Items[args.Index] as EnumItem)?.Name, args.Font,
                new SolidBrush(args.ForeColor), args.Bounds, strFmt);
        };

        listBox.MouseClick += (sender, args) =>
        {
            int index = ((ListBox)sender).IndexFromPoint(args.Location);
            if (index < 0) return;
            editorService.CloseDropDown();
        };

        listBox.KeyDown += (sender, args) =>
        {
            if (args.KeyCode != Keys.Enter) return;
            editorService.CloseDropDown();
        };

        listBox.PreviewKeyDown += (sender, args) =>
        {
            if (args.KeyCode != Keys.Escape) return;
            cancel = true;
            editorService.CloseDropDown();
        };

        if (value != null)
        {
            Type enumType = value.GetType();
            if (!enumType.IsEnum) throw new InvalidOperationException();

            foreach (FieldInfo fi in enumType.GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                EnumItem item = new EnumItem
                {
                    Value = fi.GetValue(null)
                };
                object[] attributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), true);
                item.Name = attributes.Length > 0
                    ? (attributes[0] as DescriptionAttribute)?.Description
                    : fi.Name;
                int index = listBox.Items.Add(item);
                if (fi.Name == value.ToString())
                    listBox.SetSelected(index, true);
            }
        }

        listBox.ItemHeight += 6;
        // 设置列表显示的高度
        listBox.Height = listBox.ItemHeight * listBox.Items.Count + 3;
        cancel = false;
        editorService.DropDownControl(listBox);
        return cancel || listBox.SelectedIndices.Count == 0 ? value : (listBox.SelectedItem as EnumItem)?.Value;
    }
}

public class EnumConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (!(value is string)) return base.ConvertFrom(context, culture, value);
        var type = context.GetValue<Type>("PropertyType");
        var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static)
            .FirstOrDefault(f =>
            {
                if (!(f.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)) return false;
                return description.Description.Equals(value.ToString());
            });

        if (type != null && field != null)
            return Enum.Parse(type, field.Name);

        return base.ConvertFrom(context, culture, value);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,
        Type destinationType)
    {
        // 将Enum类型转换成string进行显示
        if (destinationType != typeof(string)) return base.ConvertTo(context, culture, value, destinationType);
        var type = context.GetValue<Type>("PropertyType");
        var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static)
            .FirstOrDefault(f => f.Name.Equals(value.ToString()));

        if (field != null && field.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)
            return description.Description;

        return base.ConvertTo(context, culture, value, destinationType);
    }
}

使用

[Editor(typeof(EnumEditor), typeof(UITypeEditor)),
 TypeConverter(typeof(Forms.Utility.EnumConverter))]
public enum Alignment
{
    [Description("无")]
    None,

    [Description("居左")]
    Left,

    [Description("居中")]
    Center,

    [Description("居右")]
    Right
}

http://www.niftyadmin.cn/n/5536522.html

相关文章

基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用

基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用 一、功能描述: 上位机通过CAN总线实现对电机的运动控制,主要包含三种模式:位置模式、速度模式以及力矩模式。驱动器硬件核心为STM32F103C8T6,带相电压采集电路以及母线电压采集电路。其中供电电压12V。 PWM中心对…

步进电机(STM32+28BYJ-48)

一、简介 步进电动机&#xff08;stepping motor&#xff09;把电脉冲信号变换成角位移以控制转子转动的执行机构。在自动控制装置中作为执行器。每输入一个脉冲信号&#xff0c;步进电动机前进一步&#xff0c;故又称脉冲电动机。步进电动机多用于数字式计算机的外部设备&…

STM32 HAL库实现硬件IIC通信

文章目录 一. 前言二. 关于IIC通信三. IIC通信过程四. STM32实现硬件IIC通信五. 关于硬件IIC的Bug 一. 前言 最近正在DIY一款智能电池&#xff0c;需要使用STM32F030F4P6和TI的电池管理芯片BQ40Z50进行SMBUS通信。SMBUS本质上就是IIC通信&#xff0c;项目用到STM32CubeMXHAL库…

ListView 的简单使用及 ArrayAdapter 中参数详解

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD&#xff0c;日常还会涉及Android开发工作。 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起…

记录一次Apache Tomcat 处理返回自定义的404页面

记录工作中遇到处理访问tomcat 不存在的资源&#xff0c;返回自定义的404页面 删除webapps目录下的example、docs、manager、hta-manager目录&#xff0c;只保留 ROOT目录&#xff0c;应用部署在了这个目录 删除 manager、hta-manager 我没有发现有什么异常 制作404.jsp 或者 4…

windows USB 设备驱动开发-USB设备描述符

USB的描述符是USB设备向主机报告状态的重要数据结构&#xff0c;在USB通电后&#xff0c;端点(也称为终结点)0始终处于可用状态&#xff0c;这个默认的端点就是用于主机从设备中读取描述符的。 讨论USB通讯&#xff0c;需要从软件和硬件两方面说起&#xff0c;在软件上&#x…

车牌号查车辆信息-车牌号查车辆信息接口-汽车API接口

接口简介&#xff1a;输入车牌号&#xff0c;返回车辆相关信息&#xff08;无车主信息&#xff09;。初始登记日期、上险日期、保险到期时间、车架号、品牌这些数据会返回&#xff0c;其他数据不一定全部返回&#xff0c;,详细参数请查看返回接口文档 一般在新车上险或过户后第…

机器学习复习总结

目录 第一章 机器学习的概念及其应用 1.1机器学习的特点&#xff1a; **1.2机器学习的分类&#xff1a; 1.2.1监督学习&#xff1a; 1.2.2无监督学习&#xff1a; 1.2.3强化学习&#xff1a; 1.2.4三种机器学习的区别 *1.3深度学习 1.3.1深度学习的实质&#xff1a; …