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

转自:http://blog.sina.com.cn/s/blog_59cea87f0101g69d.html

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

首先来一段官方资料:
UITypeEditor 类 提供可用于设计值编辑器的基类,这些编辑器可提供用户界面(UI),用来表示和编辑所支持的数据类型的对象值。 
UITypeEditor类提供了一个基类,您可以从其派生或将其扩展,来为设计时环境实现一个自定义类型编辑器。通常,您的自定义类型编辑器与 PropertyGrid 控件进行交互。 
在文本框值编辑器不足以有效地选择某些类型的值的情况下,自定义类型编辑器非常有用。
若要实现自定义设计时 UI 类型编辑器,必须执行下列步骤:
定义一个从 UITypeEditor 派生的类。
重写 EditValue 方法以处理用户界面、用户输入操作以及值的分配。
重写 GetEditStyle 方法,以便将编辑器将使用的编辑器样式的类型通知给“属性”窗口。
 

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

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

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

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

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

    1. 首先建立一个usercontrol

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

    以下是源码 :

     public partial classPropertyFundStatus : UserControl
       {
           private boolcanceling;
           private FundStatus_oldfundstatus;
           private FundStatus_newfundstatus;
           publicPropertyFundStatus(FundStatus fundstatus)
           {
              _oldfundstatus = fundstatus;
              _newfundstatus = fundstatus;
              InitializeComponent();
           }

           public FundStatusFundStatus
           {
              get { return _newfundstatus; }
           }

           protected override bool ProcessDialogKey(KeyskeyData) //重写键盘接收处理ESC
           {
              if (keyData == Keys.Escape)
              {
                 _oldfundstatus = _newfundstatus;
                  canceling= true;
              }
              returnbase.ProcessDialogKey(keyData);
           }
          // 离开控件保存值
           private voidPropertyFundStatus_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 voidPropertyFundStatus_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;
           }

     

       }

    2. 这个自定义控件三个选项值保存在FundStatus类

    public class FundStatus
       {
           ///
           /// 正常
           ///
           private bool _normal =false;
           ///
           /// 注销
           ///
           private bool _cancel =false;
           ///
           /// 冻结
           ///
           private bool _frozen =false;

           public boolNormal
           {
              get { return _normal; }
              set { _normal = value; }
           }
           public boolCancel
           {
              get { return _cancel; }
              set { _cancel = value; }
           }
           public boolFrozen
           {
              get { return _frozen; }
              set { _frozen = value; }
           }

     

       }
    3. 说了这些还没有到说到正题,下面来介绍自定义控件的属性
     自定义控件[ComboFund]属性
       [ Editor(typeof (FundStatusEditor), typeof(UITypeEditor)),   //属性编辑器接口
          TypeConverter(typeof (FundStatusConverter))           //值转化器
          DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]    //序列化内容保存设置的值
           publicFundStatus FundStatus
          {
              get { return this._fundType;}
              set
              {
                 if (this._fundType != value)
                 {
                    this._fundType = value;
                    this.Reset();
                 }
              }
          }
    自定义控件的构造函数里面需要实例化这个Fundstatus
     _fundType = new FundStatus();      //这个比较重要,最开始的时候这个忘记实例化了,调了半天。

    4.注意到TypeConverter(typeof(FundStatusConverter))这个特性
     public class FundStatusConverter :TypeConverter
        {
            ///
            /// 是否能用string转换到fundstatus类型。
            ///     
            publicoverride bool CanConvertFrom(ITypeDescriptorContext context, TypesourceType)
            {
                if (sourceType ==typeof(String)) return true;
                //这里也可以是其它类型的,可以参考后面的链接里面有介绍
                returnbase.CanConvertFrom(context, sourceType);
            }
            ///
            ///能否从fundstatus转换到string
            ///   
            publicoverride bool CanConvertTo(ITypeDescriptorContext context, TypedestinationType)
            {
              if (destinationType ==typeof( FundStatus )) returntrue;

                // if (destinationType ==typeof(InstanceDescriptor)) return true;

                returnbase.CanConvertTo(context, destinationType);
            }

            ///
           ///从string转到 Fundstatus 类型。在Property窗口中显示为string类型。
            ///     
            publicoverride object ConvertTo(ITypeDescriptorContext context,System.Globalization.CultureInfo culture, object value, TypedestinationType)
            {
                String result = "";
                if (value == null) returnresult;
                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 });
                }
                returnbase.ConvertTo(context, culture, value, destinationType);
            }

            ///
            ///从 fundstatus转换为string
            ///      
            publicoverride object ConvertFrom(ITypeDescriptorContext context,System.Globalization.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;
                }
                returnbase.ConvertFrom(context, culture, value);
            }
    5.说到这里最重要的东西还没有讲,继承基类UITypeEditor的FundStatusEditor 
      publicclass FundStatusEditor : UITypeEditor
        {
              [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)] 
            publicoverride System.Drawing.Design.UITypeEditorEditStyleGetEditStyle(System.ComponentModel.ITypeDescriptorContextcontext)
            {
                if (context != null&& context.Instance != null)
                {
    //这里设置下拉模式,还有弹出框的模式
                    returnUITypeEditorEditStyle.DropDown;
                }
                returnbase.GetEditStyle(context);
            }
              [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)] 
            publicoverride objectEditValue(System.ComponentModel.ITypeDescriptorContextcontext,
                System.IServiceProviderprovider, object value)
            {
                IWindowsFormsEditorServi ceeditorService = null;
                if (context != null&& context.Instance != null&& provider != null)
                {
                    editorService=(IWindowsFormsEditorServi ce)provider.GetService(typeof(IWindowsFormsEditorServi ce));
                    if (editorService != null)
                    {
    // ComboFund 自定义控件
                        ComboFund control = (ComboFund)context.Instance;
                    PropertyFundStatus pfs = newPropertyFundStatus(control.FundStatus);
                    editorService.DropDownControl(pfs);
                     value =pfs.FundStatus;
                        returnvalue;
                    }
                }
                return value;
            }
        }

    6.这些搞完后如下图,这个就是我们要的属性选择,当然我们还可以做成弹出框的样式还有自己想怎么定义样式就怎么定义,非常方便。
    C#控件开发---控件属性编辑器

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


    参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值