(转)设计时使用自定义属性编辑器持久化对象

如题,前几天写了篇C#.Net开发继承UITypeEditor接口的自定义属性编辑器  ,总觉得不完美,这个控件是用带特殊分隔符的字符串持久化对象,可以打开xx.Designer.cs文件查看Items属性,虽然实现了所要的功能,但走的不是正道,其实有更专业的做法,设计时可以参考ListBox.Items对象的持久化后的代码。人类对探索总是充满好奇心,揣到一副不到黄河心不死的心理,花了一天时间找资料动手研究终于修出正果。

(本示例基于开发自定义Component组件详细讲解)


ComponentCS组件,继承Component。

贴图图片


自定义的属性编辑器,派生UITypeEditor基类。

贴图图片


frmTester.Designer.cs文件,ComponentCS1组件设计时生成的代码。

贴图图片


按F5运行程序,程序自动加载持久化的数据,如下图:


贴图图片



测试用的对象,请观察frmTester.Designer.cs文件中该对象的持久化属性的源码。


C# Code:


/// <summary> 
/// 测试用的对象。 
/// 请观察xxx.Designer.cs文件中该对象的属性持久化。 
/// 必须定义[Serializable]属性。 
/// </summary> 
[Serializable]
public class MyObject
{
   private int _Age = 0;
   private string _Item = "";
   private string[] _MyFavorite;
   private MyEnumType _EnumType;
   private Point _Location;
   private DateTime? _BirthDay;
   private ArrayList _Objects;
   
   public MyObject()
   {
      _Objects = new ArrayList();
   }
   
   /// <summary> 
   /// 持久化嵌套的对象数组,.Net设计器将对象持久化到res文件中 
   /// </summary> 
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
   [Localizable(true)]
   public ArrayList Objects
   {
      get { return _Objects; }
      set { _Objects = value; }
   }
   
   //枚举类型 
   public MyEnumType EnumType
   {
      get { return _EnumType; }
      set { _EnumType = value; }
   }
   
   public Point Location
   {
      get
      {
         return _Location;
      }
      set
      {
         _Location = value;
      }
   }
   
   public int Age
   {
      
      get { return _Age; }
      set { _Age = value; }
   }
   
   /// <summary> 
   /// 定义可空类型 
   /// </summary> 
   public DateTime? BirthDay
   {
      get { return _BirthDay; }
      set { _BirthDay = value; }
   }
   
   public string Item
   {
      get { return _Item; }
      set { _Item = value; }
   }
   
   public override string ToString()
   {
      //用于在Properties Window内显示的名称 
      return "(MyObject)";
   }
   
   /// <summary> 
   /// 测试持久化字符串数组 
   /// </summary> 
   public string[] MyFavorite
   {
      get { return _MyFavorite; }
      set { _MyFavorite = value; }
   }
   
}

//来源:C/S框架网(www.csframework.com) QQ:1980854898

 





自定义组件:


C# Code:

[Designer(typeof(MyComponentDesigner), typeof(IDesigner))]
[DefaultProperty("Object")]
public partial class ComponentCS : Component
{
   
   /// <summary> 
   /// 嵌套的对象,打开属性编辑器可修改这个对象 
   /// </summary> 
   private MyObject _Object = new MyObject();
   
   public ComponentCS(IContainer container)
   : base()
   {
      container.Add(this);
   }
   
   /// <summary> 
   /// 嵌套的对象,打开属性编辑器可修改这个对象 
   /// </summary> 
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
   [Editor(typeof(MyItemEditor), typeof(UITypeEditor))]
   [LocalizableAttribute(true)]
   [Category("Appearance")]
   [Description("MyObject类型对象")]
   public MyObject Object
   {
      get { return _Object; }
      set { _Object = value; }
   }
   
}

 

//来源:C/S框架网(www.csframework.com) QQ:1980854898


自定义的属性编辑器:


C# Code:


/// <summary> 
///自定义的属性编辑器 
/// </summary> 
public class MyItemEditor : UITypeEditor
{
   public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
   {
      return UITypeEditorEditStyle.Modal;
   }
   
   public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
   {
      if (provider != null)
      {
         IWindowsFormsEditorService svc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
         
         if (svc != null && context.Instance != null)
         {
            //取出设计器所在的窗体(组件/控件所在窗体) 
            IDesignerHost host = (IDesignerHost)provider.GetService(typeof(IDesignerHost));
            if (host == null) return value;
            
            //context.Instance:可以得到当前的Component1组件。 
            ComponentCS c = context.Instance as ComponentCS;
            MyObject o = c.Object;
            if (o == null) o = new MyObject();
            
            frmMyObjectEditor editForm = new frmMyObjectEditor(o);
            svc.ShowDialog(editForm);//打开属性编辑窗体 
            editForm.Dispose();//释放内存 
            
            //重新序列化内容到.Designer.cs文件 
            context.PropertyDescriptor.SetValue(context.Instance, value);
            
            return o;//返回修改后的对象 
         }
      }
      
      return value; //返回预设的对象 
   }
}

//来源:C/S框架网(www.csframework.com) QQ:1980854898

 





自定义设计器:


贴图图片

C# Code:


/// <summary> 
/// 自定义设计器 
/// </summary> 
public class MyComponentDesigner : ComponentDesigner
{
   public MyComponentDesigner()
   : base()
   {
      // 添加"编辑Items"到右键菜单和智能标记中。 
      DesignerVerb verb = new DesignerVerb("编辑Items", new EventHandler(OnDesignItems));
      this.Verbs.Add(verb);
   }
   
   private void OnDesignItems(object sender, EventArgs e)
   {
      this.DoDefaultAction();
   }
   
   // 1、可以设计Component的默认事件创建方法签名,并将用户的光标定位到该位置。 
   // 2、也可以为Component添加双击时要进行的操作。 
   public override void DoDefaultAction()
   {
      ComponentCS c = this.Component as ComponentCS;
      
      if (c.Object == null) c.Object = new MyObject();
      
      frmMyObjectEditor editor = new frmMyObjectEditor(c.Object);
      
      //调用属性编辑窗体编辑对象 
      if (DialogResult.OK == editor.ShowDialog())
      {
         //取出Object属性的PropertyDescriptor,派生类:ReflectPropertyDescriptor 
         //PropertyDescriptor:是抽象基类. 
         PropertyDescriptor pd = TypeDescriptor.GetProperties(c)["Object"];
         
         //当设计器修改了对象的属性,持久化属性的值到Designer.cs文件。 
         if (pd != null) pd.SetValue(c, c.Object);
      }
      
      editor.Dispose();
   }
}


//来源:C/S框架网(www.csframework.com) QQ:1980854898

 

C/S框架网原创作品,如转载请注明出处:www.csframework.com

posted @ 2012-09-08 12:06  C#老头子  Views(1821)  Comments(0)    收藏  举报