C#組件編程(2)

C#組件編程(2)

較复雜的屬性為了編輯方便,就要用到屬性編輯器.
由于在屬性視窗中只能識別字符串類型,如果是非字符串類型的屬性還需要用到類型轉換器.
下面就分別講它們的使用方法:

1.屬性編輯器Property Editor
在vs环境中Property Editor有两种,一种是vs自带的,一种是Component编写者根据自己需求而重新编写的。

示例:
 using System;
 using System.Collections.Generic;
 using System.Collections;
 using System.Text;
 using System.ComponentModel;
 using System.ComponentModel.Design;
 using System.Drawing;
 using System.Drawing.Design;
 using System.Windows.Forms;
 using System.Windows.Forms.Design;
 
 namespace Components
  {
     // 这个例子用到了vs 2005里的List<>.
     public class Demo3 : Component
      {
         public Demo3()
         {
             _students = new List<Student>(); // 一定要在构造函数中实例化_students。
         }
 
         private List<Student> _students;
         private string _grade;
 
         // 使用 vs自带的Editor。
         // 如果没有DesignerSerializationVisibilityAttribute的话,对Students设值,值不能被保存。
         // 大家可以把DesignerSerializationVisibilityAttribute注释掉,对Students设值后,关闭vs环境,再重新打开项目,观察Students的值没有被保存下来。
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
         public List<Student> Students
          {
              get { return _students; }
              set { _students = value; }
         }
 
         //使用用户自定义的Editor。
         [Editor(typeof(GradeEditor), typeof(UITypeEditor)), LocalizableAttribute(true)]
         public string Grade
          {
              get { return _grade; }
              set { _grade = value; }
         }
     }
 
     public class Student
      {
         private int _id;
         private string _name;
 
         public int Id
          {
              get { return _id; }
              set { _id = value; }
         }
 
         public string Name
          {
              get { return _name; }
              set { _name = value; }
         }
     }
 
     /*//在vs2003中實現集合的方式,這比在vs2005中使用泛型复雜多了.
     public class StudentCollection : CollectionBase,IList 
      {
        public Student this[int index]
        {
            get { return (Student)(List[index]); }
            set { List[index] = value; }
        }

        public int Add(Student value)
        {
            return List.Add(value);
        }

        public int IndexOf(Student value)
        {
            return List.IndexOf(value);
        }

        public bool Contains(Student value)
        {
            return List.Contains(value);
        }

        public void Remove(Student value)
        {
            List.Remove(value);
        }
     } */
 
     public class GradeEditor : UITypeEditor
      {
         [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)]
         public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
          {
             // UITypeEditorEditStyle有三种,Modal是弹出式,DropDown是下拉式,None是没有。
             return UITypeEditorEditStyle.Modal;
         }
 
         [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand)]
         public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
          {
             // 得到editor service,可由其创建弹出窗口。
             IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
 
             // context.Instance —— 可以得到当前的Demo3对象。
             // ((Demo3)context.Instance).Grade —— 可以得到当前Grade的值。
 
             frmGradeEditor dialog = new frmGradeEditor();
             editorService.ShowDialog(dialog);
             String grade = dialog.Grade;
             dialog.Dispose();
             
             return grade;
         }
     }
 }

2.TypeConverterAttribute(类型转换)

示例:
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Globalization;

namespace ClassLibrary1
{
    public class Class1 : Component
    {
        private Size _size;

        public Class1()
        {
            _size = new Size();
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [TypeConverter(typeof(SizeConverter))]       //  —— 注1,也可以把这句TypeConverterAttribute写在注2处。
        public Size Size
        {
            get { return _size; }
            set { _size = value; }
        }
    }

    public class SizeConverter : TypeConverter     // 我们自定义的Converter必须继承于TypeConverter基类。
    {
        /// <summary>
        /// 是否能用string转换到Size类型。
        /// </summary>
        /// <param name="context">上下文。</param>
        /// <param name="sourceType">转换源的Type。</param>
        /// <returns></returns>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
            { return true; }
            else
            { return false; }
        }

        /// <summary>
        /// 从string转到Size类型。
        /// </summary>
        /// <param name="context">提供Component的上下文,如Component.Instance对象等。</param>
        /// <param name="culture">提供区域信息,如语言、时间格式、货币格式等</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value == null || value.ToString().Length == 0) return new Size();
            char spliter = culture.TextInfo.ListSeparator[0];    // 得到字符串的分隔符
            string[] ss = ((string)value).Split(spliter);

            Int32Converter intConverter = new Int32Converter();   // 得到类型转换器,.net中为我们定义了一些常见的类型转换器。
            return new Size((Int32)intConverter.ConvertFromString(context, culture, ss[0]), 
               (Int32)intConverter.ConvertFromString(context, culture, ss[1]));
        }

        /**//// <summary>
        /// 是否能用Size转换到string类型。
        /// </summary>
        /// <param name="context"></param>
        /// <param name="destinationType">转换目标的类型。</param>
        /// <returns></returns>
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(Size))  // 如果是Size格式,则允许转成string。
            { return true; }
            else
            { return false; }
        }

        // 在Property窗口中显示为string类型。
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (value == null) return string.Empty;
            if (destinationType == typeof(string))
            {
                Size size = (Size)value;
                TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(Int32));   // 得到类型转换器的另一种方式。
                char spliter = culture.TextInfo.ListSeparator[0];    // 得到字符串的分隔符

                return string.Join(spliter.ToString(), new string[]{
                intConverter.ConvertToString(context, culture, size.Length),
                    intConverter.ConvertToString(context, culture, size.Width)});
            }
            return string.Empty;
        }

        // TypeConverter还有几个虚方法,请大家自己研究。
    }

    // [TypeConverter(typeof(SizeConverter))]     —— 注2
    public class Size
    {
        private Int32 _length;
        private Int32 _width;

        public Size(Int32 length, Int32 width)
        {
            _length = length;
            _width = width;
        }

        public Size() : this(0, 0)
        {
        }

        public Int32 Length
        {
            get { return _length; }
            set { _length = value; }
        }

        public Int32 Width
        {
            get { return _width; }
            set { _width = value; }
        }
    }
}

 

你可能感兴趣的:(object,String,C#,dropdown,Class,dialog)