C#控件开发之属性编辑器

我们知道默认的属性一般都是下拉输入之类的,也有多选,但是我需要的是checkbox,没有现成的,百度发现微软有提供接口UITypeEditor ,继承这个基类就可以搞定了。废话不多说了,下面来具体代码说明。

首先来一段官方资料:

UITypeEditor 类 提供可用于设计值编辑器的基类,这些编辑器可提供用户界面(UI),用来表示和编辑所支持的数据类型的对象值。 

UITypeEditor类提供了一个基类,您可以从其派生或将其扩展,来为设计时环境实现一个自定义类型编辑器。通常,您的自定义类型编辑器与 PropertyGrid 控件进行交互。 

在文本框值编辑器不足以有效地选择某些类型的值的情况下,自定义类型编辑器非常有用。

若要实现自定义设计时 UI 类型编辑器,必须执行下列步骤:

定义一个从 UITypeEditor 派生的类。

重写 EditValue 方法以处理用户界面、用户输入操作以及值的分配。

重写 GetEditStyle 方法,以便将编辑器将使用的编辑器样式的类型通知给“属性”窗口。

一、引用

using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Drawing.Design;
using System.Globalization;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.Design;

二、源控件及关联的属性

自定义控件[ComboFund]属性

自定义控件的构造函数里面需要实例化这个Fundstatus

 _fundType = new FundStatus();      //这个比较重要,最开始的时候这个忘记实例化了,调了半天。

/// <summary>
/// 源控件
/// </summary>
public class ComboFund : Control
{

    private FundStatus _FundStatus;

    [Editor(typeof(FundStatusEditor),typeof(UITypeEditor))]   //属性编辑器接口
    [TypeConverter(typeof(FundStatusConverter))]           //值转化器
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]   //序列化内容保存设置的值

    public FundStatus FundStatus
    {
        get { return this._FundStatus; }
        set { if (this._FundStatus != value) { this._FundStatus = value; } }
    }

    /// <summary>
    /// 【构造函数】在构造控件的时必须属性值初始化
    /// </summary>
    public ComboFund()
    {
        _FundStatus = new FundStatus();
    }

}

三、属性值的类

public class FundStatus
{
    /// <summary>【缓存变量】正常</summary>
    private bool _normal = false;
    /// <summary>【缓存变量】注销</summary>
    private bool _cancel = false;
    /// <summary>【缓存变量】冻结</summary>
    private bool _frozen = false;

    public bool Normal { get { return _normal; } set { _normal = value; } }

    public bool Cancel { get { return _cancel; } set { _cancel = value; } }

    public bool Frozen { get { return _frozen; } set { _frozen = value; } }
}

四、属性值编辑器的可视化控件

通过执行下列步骤,可以为在“属性”窗口中绘制值的表示形式添加附加支持:

重写 GetPaintValueSupported 方法以指示编辑器支持显示值的表示形式。

重写 PaintValue 方法以实现该值的表示形式的显示。

如果编辑器应具有初始化行为,则重写 UITypeEditor 构造函数方法。

下面是checkbox属性下拉框的例子:

public partial class PropertyFundStatus : UserControl
{
    private bool canceling;
    private FundStatus _oldfundstatus;
    private FundStatus _newfundstatus;

    private CheckBox hscb_normal;
    private CheckBox hscb_Frozen;
    private CheckBox hscb_Cancel;
    public PropertyFundStatus(FundStatus fundstatus)
    {
        _oldfundstatus = fundstatus;
        _newfundstatus = fundstatus;
    }

    public FundStatus FundStatus
    { get { return _newfundstatus; } }

    protected override bool ProcessDialogKey(Keys keyData) //重写键盘接收处理ESC
    {
        if (keyData == Keys.Escape)
        {
            _oldfundstatus = _newfundstatus;
            canceling = true;
        }
        return base.ProcessDialogKey(keyData);
    }
    // 离开控件保存值
    private void PropertyFundStatus_Leave(object sender, EventArgs e)
    {
        if (!canceling)
        {
            //保存值
            if (hscb_normal.Checked) { _newfundstatus.Normal = true; }
            else { _newfundstatus.Normal = false; }
            if (hscb_Frozen.Checked) { _newfundstatus.Frozen = true; }
            else { _newfundstatus.Frozen = false; }
            if (hscb_Cancel.Checked) { _newfundstatus.Cancel = true; }
            else { _newfundstatus.Cancel = false; }
        }
    }

    //加载属性控件的时候赋值
    private void PropertyFundStatus_Load(object sender, EventArgs e)
    {
        //赋值
        hscb_normal.CheckState = _oldfundstatus.Normal ? CheckState.Checked : CheckState.Unchecked;
        hscb_Frozen.CheckState = _oldfundstatus.Frozen ? CheckState.Checked : CheckState.Unchecked;
        hscb_Cancel.CheckState = _oldfundstatus.Cancel ? CheckState.Checked : CheckState.Unchecked;
    }

}
  • 五、类别转换器(值转化器)

注意到TypeConverter(typeof(FundStatusConverter))这个特性

public class FundStatusConverter : TypeConverter
{

    /// <summary>
    /// 是否能用string转换到fundstatus类型。
    /// </summary>
    /// <param name="context"></param>
    /// <param name="sourceType"></param>
    /// <returns></returns>
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(String)) return true;
        //这里也可以是其它类型的,可以参考后面的链接里面有介绍
        return base.CanConvertFrom(context, sourceType);
    }

    /// <summary>
    /// 能否从fundstatus转换到string。
    /// </summary>
    /// <param name="context"></param>
    /// <param name="destinationType"></param>
    /// <returns></returns>
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(FundStatus)) return true;
        // if (destinationType ==typeof(InstanceDescriptor)) return true;
        return base.CanConvertTo(context, destinationType);
    }

    /// <summary>
    /// 从string转到 Fundstatus 类型。在Property窗口中显示为string类型。
    /// </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)
    {
        String result = "";
        if (value == null) return result;
        if (destinationType == typeof(String))
        {
            //这里处理选择后在属性框里面显示的值
            FundStatus scope = (FundStatus)value;
            if (scope.Normal)
            {
                if (result.Length > 0) { result += ",normal"; }
                else { result += "normal"; }
            }
            else { result = result.Replace("normal", "").Replace(",normal", ""); }
            if (scope.Cancel)
            {
                if (result.Length > 0) { result += ",cancel"; }
                else { result += "cancel"; }
            }
            else { result = result.Replace("cancel", "").Replace(",cancel", ""); }
            if (scope.Frozen)
            {
                if (result.Length > 0) { result += ",frozen"; }
                else { result += "frozen"; }
            }
            else { result = result.Replace("frozen", "").Replace(",frozen", ""); }
            return result;
            }
            if (destinationType == typeof(InstanceDescriptor))
        {
            ConstructorInfo ci = typeof(FundStatus).GetConstructor(new Type[] { typeof(bool), typeof(bool), typeof(bool) });
            FundStatus scope = (FundStatus)value;
            return new InstanceDescriptor(ci, new object[] { scope.Cancel, scope.Frozen, scope.Normal });
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }

    /// <summary>
    /// 从 fundstatus转换为string
    /// </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 == null || value.ToString().Length == 0) return new FundStatus();
        if (value is string)
        {
            //String[] v = ((String)value).Split(',');
            string tempvalue = (string)value;
            FundStatus csf = new FundStatus();
            csf.Cancel = tempvalue.Contains("cancel");
            csf.Frozen = tempvalue.Contains("frozen");
            csf.Normal = tempvalue.Contains("normal");
            return csf;
        }
        return base.ConvertFrom(context, culture, value);
    }
}

六、源控件属性和属性编辑器关联类

public class FundStatusEditor : UITypeEditor
{

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)]
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        if (context != null && context.Instance != null)
        {
            //这里设置下拉模式,还有弹出框的模式
            return UITypeEditorEditStyle.DropDown;
        }
        return base.GetEditStyle(context);
    }

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)]
    public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService editorService = null;
        if (context != null && context.Instance != null && provider != null)
        {
            editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if (editorService != null)
            {
                // ComboFund 自定义控件
                ComboFund control = (ComboFund)context.Instance;
                PropertyFundStatus pfs = new PropertyFundStatus(control.FundStatus);
                editorService.DropDownControl(pfs);
                value = pfs.FundStatus;
                return value;
            }
        }
        return value;
    }
}

七、运行结果

参考资料

​​​​​​UITypeEditor 类 (System.Drawing.Design) | Microsoft Learn​​​​​​

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值