引入

在设计用户控件的时候(不管是winform还是webform),对于一般的简单属性(string,int,bool……基元类型)系统会为我们自动提供相应的类型转换。举个例子:我们在用户控件中定义一个Age属性,

        public int Age{get;set;}

这时我们打开设计器,就会看到

这个属性了。我们可以随便为其设置int类型的值。但是当我们试着填写一个string类型的字符时,系统就会弹出一个“属性无效”窗口,在这个过程中我们就可以看出系统已经为Age做了类型转换,而且这个转换失败了,因为类型不匹配。

现在让我们再写一个复杂点的属性Person。先创建一个Person类,它里面包含了name和age属性:

    public class Person{private string strName;private int intAge;public string StrName{get { return strName; }set { strName = value; }}public int IntAge{get { return intAge; }set { intAge = value; }}}

然后在用户控件中,我们新建一个person的属性:

        private Person person;public Person Person{get { return person; }set { person = value; }}

打开设计器窗体后我们可以看到Person属性是灰色的

为什么会这样呢?答案很简单,系统不知道如何去显示这个属性。但总得显示点儿什么吧?于是无可奈何下显示了person类的类型名。这与我们所期望的形如Location样式的可差远了

到底差在哪里呢?类型转换器!当我们在Person里面填写"zhangsan,21"的时候,类型转换器就能自动将这两个属性值对应到strName,intAge上面去,这就是类型转换器的作用。那么下面我们就来实现一个person的类型转换器。

实现类型转换器

首先新建一个新类PersonConverter,用于提供person类型转换的能力,所有的注释我都写在代码里面了,大家一看就明白:

代码public class PersonConverter:TypeConverter{//指示我们设置的内容能否转换//因为我们输入的是“zhangsan,12”的字符串形式,所以这里接受字符串类型的转换public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType){return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);}//这个方法指示了最后的这个复杂属性是以什么形式表现出来的。//如果destinationType == typeof(string)的话,最后person显示的就是"zhangsan,21"的形式//如果destinationType == typeof(InstanceDescriptor)的话,person显示的就是"WindowsFormsControlLibrary1.Person"类名的形式。public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType){if (destinationType == typeof(string)){return true;}if (destinationType == typeof(InstanceDescriptor)){return true;}return base.CanConvertTo(context, destinationType);}//这个方法实现了我们输入的字符串如何被转化为person类型public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value){if (value is string){String[] v = ((String)value).Split(',');if (v.GetLength(0) != 2){throw new ArgumentException("Invalid parameter format");}Person csf = new Person { Name = Convert.ToString(v[0]), Age = Convert.ToInt32(v[1]) };return csf;}return base.ConvertFrom(context, culture, value);}//这个则是实现了具体如何显示person这个属性的方法public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType){if (destinationType == typeof(String)){Person scope = (Person)value;String result = scope.Name.ToString() + "," + scope.Age.ToString();return result;}if (destinationType == typeof(InstanceDescriptor)){ConstructorInfo ci = typeof(Person).GetConstructor(new Type[] { typeof(string), typeof(Int32) });Person scope = (Person)value;return new InstanceDescriptor(ci, new object[] { scope.Name, scope.Age });}return base.ConvertTo(context, culture, value, destinationType);}//以下两个方法提供子属性单独设置的能力。public override bool GetPropertiesSupported(ITypeDescriptorContext context){return true;}public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes){return TypeDescriptor.GetProperties(typeof(Person), attributes);}}

然后在用户控件的person属性上加上这么一句,指定了person的转换器:

        [TypeConverter(typeof(PersonConverter))]public Person Person{get;set;}

我们现在再来看看person的设计时的样子,这样就和我们需求的一样了。

这里再教大家一个偷懒的方法,就是实现转换器的时候不必重写最上面的那四个方法,直接重写“提供子属性单独设置的能力”的两个方法就是了。只不过这样person属性显示的效果如下:

就是person显示的内容变了,子属性还是提供设置。对于要求不高的属性也够了。

实现模态属性编辑器

前面我们实现了形如Location属性的设计时属性设置支持,但我们有时需要的可能不只是这么复杂的属性设置。比如BackgroundImage这个属性,当我们设置它的时候,系统会弹出一个界面出来让我们选择图片:

使用这种方式无疑增加了我们选择图片的方便度。那这种形式的设置该如何实现呢?

首先我们新建一个窗体,这个窗体就是将来需要显示给用户设置属性的(比如上图的“选择资源”窗体)。我们还是以person类为例:

该窗体的后台代码如下:

代码private Person _person;public PersonWindow(Person person){InitializeComponent();Person = person;textBox1.Text = person.StrName;textBox2.Text = person.IntAge.ToString();}public Person Person{get { return _person; }set { _person = value; }}/// <summary>/// 确认按钮/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button1_Click(object sender, EventArgs e){Person.StrName = textBox1.Text;Person.IntAge = int.Parse(textBox2.Text);}

这里要注意的一点就是confirm按钮的DialogResult要设置为DialogResult.OK,cancel按钮的DialogResult要设置为DialogResult.Cancel。至于为什么要这么做大家往后看就知道了。

然后我们再建立一个class PersonModalEditor:System.Drawing.Design.UITypeEditor类,其代码如下:

代码public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context){//指示以什么样的形式打开编辑窗体return UITypeEditorEditStyle.Modal;}//属性编辑方法,当我们单击属性窗口中的属性按钮时会执行这个方法。public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value){//获取服务对象,这个对象专门为winform编辑器提供一些功能IWindowsFormsEditorService service =(IWindowsFormsEditorService) provider.GetService(typeof (IWindowsFormsEditorService));if (service==null){return null;}Person p = new Person();CategoryWindow form = new CategoryWindow(p);//这里知道为什么要设置confirm按钮的DialogResult属性的原因了吧。if (service.ShowDialog(form) == System.Windows.Forms.DialogResult.OK){return p;}return value; //系统会根据这个返回值在person属性里面进行填充}

最后我们在用户控件的person属性上加上这个一句话:

        [Editor(typeof(CategoryModalEditor), typeof(UITypeEditor))]public Person Person{get { return person; }set { person = value; }}

这句话指定了系统如何打开person的属性编辑器。我们看看效果图:

用户按了confirm以后,strName和intAge属性的值就会被成功设置了。

转载于:https://www.cnblogs.com/qianlifeng/archive/2010/11/18/1881238.html

用户控件中复杂属性的设计时支持相关推荐

  1. ASP.NET开发:在用户控件中添加属性

    在WEB开发中,可重用的代码我们可以把它写成一个通用模块供需要的地方来引用.本文就是介绍在ASP.NET的web编程时,如何在用户控件中添加属性,实现这种方法:举例说明详解. 在WEB开发中经常有一些 ...

  2. WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性

    原文:WPF 使用依赖属性(DependencyProperty) 定义用户控件中的Image Source属性 如果你要自定义一个图片按钮控件,那么如何在主窗体绑定这个控件上图片的Source呢? ...

  3. 关于从页面中获取用户控件中的其它控件(如DropDownList)事件的方法

    在项目中经常把一些经常使用的代码做成用户控件以提高代码的可重用性, 一个经常遇到的就是在页面中调用用户控件中的服务器控件的事件,下面给出简单的代码示列. 我们在一个用户控件(MaterialRepor ...

  4. Asp.net 2.0 自定义控件开发专题讲解[为用户控件增加DataSource属性, 能够自动识别不同数据源](示例代码下载)...

    (一).  概要 开发<数据绑定用户控件>, 要实现一个DataSource属性, 并且能够自动识别不同的数据源, 如: ArrayList, DataTable, DataSet, XM ...

  5. 用户控件中动态加入脚本引用

    用户控件中动态加入脚本引用,添加前先判断是否已经有引用,没有才添加. //××××.ascx protected void Page_Load(object sender, EventArgs e){ ...

  6. 在用户控件中用户登录后台脚本判断

    在用户控件中用户登录后台脚本判断写法  if (!IsPostBack)         {                         imagelogin.Attributes.Add(&qu ...

  7. 用户控件中使用相对路径问题

    在用户控件中使用相对路径,会因为引用控件的页面的不同路径而产生问题.在用户控件里最好使用以站点根目录开始指定相对路径,比如你的asp.net应用程序名为:myapp,你的图片是 myapp/myima ...

  8. 解决在ascx使用outputcache就不可以设置用户控件自己的属性

    解决在ascx使用outputcache就不可以设置用户控件自己的属性 转载至:http://www.aspnetpro.com/NewsletterArticle/2003/08/asp200308 ...

  9. 如何在Web用户控件中引用样式表中的样式

    如何在Web用户控件中引用样式表中的样式 <%@ Control Language="C#" AutoEventWireup="true" CodeFil ...

  10. 如何在用户控件中操作页面中的控件?

    一般来讲我们会把功能集中在ASCX文件实现,以便能够多次使用,但在某种情况下,我们可能会用到对用户控件所在的页面容器进行操作. 其实如果想一下,道理也很简单,如果ASCX被使用了,其会出现在页面容器中 ...

最新文章

  1. hdu 2454 Degree Sequence of Graph G
  2. thinkphp上传图片自动压缩问题
  3. 【金三银四】java多线程并发编程pdf
  4. linux 命令提示符 时间,在LINUX的命令提示符及CMD命令提示符中显示时间
  5. 两台虚拟服务器如何级联,[教程] 利用open vswitch建立vxlan隧道实现不同主机上的虚拟交换机级联...
  6. 怎么样递增的注册成对的点云
  7. Visual Studio调试技巧
  8. JNI_Android项目中调用.so动态库实现详解【转】
  9. docker kali安装mysql_Linux环境使用Docker安装MySql
  10. 《并行计算的编程模型》一3.1 引言
  11. 微软私有云分享(R2)21 BMC提升B格
  12. js返回页面并刷新页面数据
  13. java jdbc连接字符串加密,Java JDBC连接数据库字符串大全
  14. 工信部电子五所张志强:中国数据库行业发展趋势分析
  15. Q3手机银行运营报告:直销银行江湖再起波澜,数字员工助力手机银行活跃度提升
  16. android 拨打带有分机号的电话
  17. python编程:从入门到实践 阅读笔记
  18. 解决安装pycrypto时的各种问题/安装失败
  19. jbpm学习笔记(九) task活动之泳道的概念
  20. 如何无损增大C盘容量

热门文章

  1. mysql基础之视图、事务、索引、外键
  2. break 和 continue
  3. How to create a angular2 project process
  4. 关于setTimeout的面试题
  5. 每日一九度之 题目1091:棋盘游戏
  6. Source Insight 中查看日文注释
  7. 11.求二元查找树的镜像[MirrorOfBST]
  8. 玩转 MPlayer(3)
  9. ext.net 开发学习——回车事件(六)
  10. 【音乐欣赏】《Sunflower》 - Post Malone / Swae Lee