[ProvideProperty("IsEnabled", typeof(LayoutControlItem)), ToolboxItemFilter("System.Windows.Forms"), Description("DevExpress自定义注册控件")]
public partial class UserContorlEnabledClick : Component, IExtenderProvider
{
#region 构造函数
private Hashtable items;//存放控件设置
private Hashtable validateItems; public UserContorlEnabledClick()
{
InitializeComponent();
items = new Hashtable();
validateItems = new Hashtable();
} public bool CanExtend(object extendee)
{
return true;
}
#endregion /// <summary>
/// 显示自定义属性(Visual Studio设计器 IExtenderProvider接口方法)
/// </summary>
public RegexContext GetIsEnabled(LayoutControlItem control)
{
if (control == null)
{
throw new ArgumentNullException("LayoutControlItem");
}
RegexContext con = EnsurePropertiesExists(control);
return con;
} /// <summary>
/// 设置自定义属性(Visual Studio设计器 IExtenderProvider接口方法)
/// </summary>
public void SetIsEnabled(LayoutControlItem control, RegexContext value)
{
RegexContext context = EnsurePropertiesExists(control);
context.IsClick = value.IsClick;
context.Validate = value.Validate;
if (context.IsClick)
{
control.Click -= item_Click;
control.Click += item_Click;
}
} /// <summary>
/// 确保扩展属性的菜单项在字典中
/// </summary>
/// <param name="key">目标菜单项</param>
/// <returns>扩展属性</returns>
private RegexContext EnsurePropertiesExists(object key)
{
RegexContext p;
if (items.ContainsKey(key))
{
p = (RegexContext)items[key];
}
else
{
p = new RegexContext();
items.Add(key, p);
}
if (!validateItems.ContainsKey(key))
{
validateItems.Add(key, p);
}
return p;
} /// <summary>
/// 点击事件
/// </summary>
private void item_Click(object sender, EventArgs e)
{
LayoutControlItem item = sender as LayoutControlItem;
if (item == null) return;
item.Control.Enabled = GetEnabled(item.Control.Enabled);
} private bool GetEnabled(bool enabled)
{
if (enabled)
return false;
else
return true;
} //private void SetFromControl(Control control)
//{
// var regexContext = userDXValidateExtender1.GetError(control);
// regexContext.AllowEmpty = !control.Enabled;
//}
}
/// <summary>
/// 属性
/// </summary>
[TypeConverter(typeof(ValidateTypeConverter)), ComVisible(true)]
public class RegexContext
{
/// <summary>
/// 异常信息
/// </summary>
private string _RegexExpression;
[Category("验证"), DefaultValue(""), Description("设置异常信息")]
public string RegexExpression
{
get { return _RegexExpression; }
set { _RegexExpression = value; }
} /// <summary>
/// 是否注册点击事件
/// </summary>
private bool _isClick;
[Category("验证"), DefaultValue(""), Description("设置点击事件enabled")]
public bool IsClick
{
get { return _isClick; }
set { _isClick = value; }
} /// <summary>
/// 是否验证控件
/// </summary>
private bool _Validate;
[Category("验证"), DefaultValue(""), Description("设置验证控件不能为空")]
public bool Validate
{
get { return _Validate; }
set { _Validate = value; }
}
} public class ValidateTypeConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
//如果目标类型是字符串,允许将自定义类型转换为字符串
if (destinationType == typeof(string))
{
return true;
}
return base.CanConvertTo(context, destinationType);
} public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
//如果要转换为自定义类型
if (destinationType == typeof(string))
{
if (value is RegexContext)
{
RegexContext ca = (RegexContext)value;
return ca.RegexExpression;
}
}
return base.ConvertTo(context, culture, value, destinationType);
} public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return false;
} public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
string strValue = value as string;
if (strValue != null)
{
string text = strValue.Trim();
if (text.Length == )
{
return null;
}
else
{
RegexContext member = new RegexContext();
return member;
}
}
return base.ConvertFrom(context, culture, value);
} public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
{
if (propertyValues == null)
{
throw new ArgumentNullException("propertyValues");
}
object regexExString = propertyValues["RegexExpression"];
object IsClick = propertyValues["IsClick"];
object Validate = propertyValues["Validate"];
RegexContext member = new RegexContext();
member.RegexExpression = (string)regexExString;
member.IsClick = (bool)IsClick;
member.Validate = (bool)Validate;
return member;
} public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
} public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value,
Attribute[] attributes)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(RegexContext), attributes);
return props.Sort(new string[]
{
"RegexExpression",
"IsClick",
"Validate"
});
} public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
}
}

1、让UserContorlEnabledClick组件实现System.ComponentModel.IExtenderProvider接口,并继承System.ComponentModel.Component类,同时用ProvidePropertyAttribute特性描述该类。实现IExtenderProvider接口就表明本类是一个【扩展程序提供程序】,MSDN有相关的示例:http://msdn.microsoft.com/zh-cn/library/ms229066(v=vs.80).aspx。那么到底是要给什么类扩展出什么属性呢,这是由ProvideProperty特性定义的,本类的目的是为【UserContorlEnabledClick】类扩展出一个叫【IsEnabled】的属性,

继承Component则是为了让UserContorlEnabledClick像LayoutControlItem那样能拖入到VS组件栏中,这样LayoutControlItem的属性窗格中才会多出一个IsEnabled属性来。、

2、实现一个public string GetIsEnabled(LayoutControlItem control)方法,作用是获取指定控件,这也是第2步中定义容器的原因,没有容器记录下各个控件及其描述属性,这个方法将难以实现。注意该方法的命名必须是Get+ProvideProperty中定义的扩展属性名,即IsEnabled,合起来就是GetIsEnabled。另外,对该方法加DefaultValue特性是必要的,不然当拖入ToolDescribe时,VS会对所有item进行扩展,不管有没有设置某个item的Describe,这点可以从InitializeComponent方法中看出来;

3、实现一个public void SetIsEnabled(LayoutControlItem control, RegexContext value)方法,命名要求同上。该方法的作用注册事件或设置属性和添加到容器里(Hashtable)。

4、自定义属性RegexContext类,及自定ValidateTypeConverter类(这个特性十分重要,可以让属性折叠显示),

效果图

我是参考大佬的博客https://www.cnblogs.com/ahdung/p/4169724.html,嘻嘻嘻

IExtenderProvider,c#组件扩展控件属性的更多相关文章

  1. ExtJs控件属性配置详细

    序言:    1.本文摘自网络,看控件命名像是4.0以前的版本,但控件属性配置仍然可以借鉴(不足之处,以后项目用到时再续完善). Ext.form.TimeField: 配置项:            ...

  2. Android控件属性大全(转)

    http://blog.csdn.net/pku_android/article/details/7365685 LinearLayout         线性布局        子元素任意: Tab ...

  3. FoxOne---一个快速高效的BS框架--WEB控件属性编辑器

    FoxOne---一个快速高效的BS框架--(1) FoxOne---一个快速高效的BS框架--(2) FoxOne---一个快速高效的BS框架--(3) FoxOne---一个快速高效的BS框架-- ...

  4. Android控件属性大全[整理转载]

    控件属性: android属性 Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料, 第一类:属性值为true或falseandroid:layout_ ...

  5. 【转载】Android控件属性大全

    控件属性: android属性 Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料, 第一类:属性值为true或falseandroid:layout_ ...

  6. DELPHI控件属性事件说明

    常用DELPHI控件属性事件设置说明 常用DELPHI控件属性设置说明目录TForm Class TPanel组件 TToolBar Class TToolButton Class TTimer Cl ...

  7. 43. ExtJs控件属性配置详细

    转自:https://www.cnblogs.com/mannixiang/p/6558225.html 序言:    1.本文摘自网络,看控件命名像是4.0以前的版本,但控件属性配置仍然可以借鉴(不 ...

  8. 2.C#Panel扩展控件

    1.解决方案下添加新建项目新建类库 2. 在项目下添加新建项选择新建组件类 3.先引用,然后导入两个命名空间 4.因为是扩展控件,把继承自Component改成继承自Panel using Syste ...

  9. 多年前写的文本框扩展控件(有ValueChanging事件等),已放github

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 阅读目录 介绍 起因 代码 使用 GitHub ...

随机推荐

  1. golang gorm框架的默认时区问题

    gorm框架的时区是在连接数据库时设置的, 如下

  2. Xshell登录Vagrant方式

    Xshell登录Vagrant方式 我上一篇文章 介绍了vagrant 如何创建虚拟机集群,在上篇文章的基础上,用xshell 登录 虚拟机发现 默认是无法使用账号密码登录root账号,只能使用vag ...

  3. UML期末复习题——2.7:UML Sequence Diagram

    第七题:顺序图 重要概念: 1. 顺序图的主要介绍,在之前对第5题“系统顺序图”的解析讲解里已经很详细了,在这里只是对部分不全面的内容进行补充. 第五题:系统顺序图&后置条件 http://w ...

  4. 周志华-机器学习西瓜书-第三章习题3.5 LDA

    本文为周志华机器学习西瓜书第三章课后习题3.5答案,编程实现线性判别分析LDA,数据集为书本第89页的数据 首先介绍LDA算法流程: LDA的一个手工计算数学实例: 课后习题的代码: # coding ...

  5. 阶段5 3.微服务项目【学成在线】_day04 页面静态化_08-freemarker基础-空值处理

    把stus注释掉 正常访问就会报错 第20行 这里的stus为空,所以造成了这个错误. 非空判断 不为空用双问号来判断 <#if stus??><#list stus as stu& ...

  6. Qt编写自定义控件21-圆弧仪表盘

    一.前言 圆弧仪表盘在整个自定义控件大全中也稍微遇到了技术难点,比如背景透明,如果采用以前画圆形画扇形的方式绘制,肯定很难形成背景透明,需要用到切割,最后换了一种绘制方法,采用绘制圆弧的方式,即使用d ...

  7. MyISAM与InnoDB之间的区别

    区别: 1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事 ...

  8. MIGO 收货

    ls_code-gm_code = '01'. 01 - MB01 - Goods Receipts for Purchase Order 02 - MB31 - Goods Receipts for ...

  9. jenkins通过ssh登不上远程主机

    https://blog.csdn.net/cdnight/article/details/81078191 就是需要切换jenkins用户,用jenkins用户生产的秘钥拷到其他主机上

  10. Flutter 的一些小技巧

    1. 获取状态栏高度 import 'dart:ui'; MediaQueryData.fromWindow(window).padding.top 2. 设置AppBar的高度 Scaffold( ...