IExtenderProvider,c#组件扩展控件属性
[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 == 0) { 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,嘻嘻嘻