IExtenderProvider接口的应用

      在Windows Form编程中,如果我们希望实现一个textbox的扩展,例如加入自定义属性或方法,很容易想到的是使用继承自textbox的自定义控件。但是这样做有时会出现一些问题,比如仅仅为了添加一个额外属性就要创建一个的自定义控件是否开销过大?某些继承出来的控件不支持在视图设计器中进行编辑等等。.Net中我们可以使用另一种方法来实现扩展控件的目的,这就是通过IExtenderProvider接口。通过它我们可以向容器中的其他控件提供额外的属性和扩展方法。比较直观的例子就是Tooltip组件,它就继承了IExtenderProvider接口。将它拖拽进一个容器内时就会发现,容器中所有的控件的属性中都新增了“toolTip1上的tooltip”这么一项属性。类似于这样就可以不必自定义控件也能扩展额外属性了。下面是我写的一个简单的例子:

None.gif using  System;
None.gif
using  System.ComponentModel;
None.gif
using  System.Collections;
None.gif
using  System.Windows.Forms;

None.gif namespace  ClassLibrary1
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Class1 的摘要说明。
InBlock.gif    
/// </summary>
InBlock.gif    
/// <summary>
InBlock.gif    
/// Component1 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    [ProvideProperty("Name"typeof(Control))]
InBlock.gif    
public class Component1 : System.ComponentModel.Component ,IExtenderProvider
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private  Hashtable _innerTable = new Hashtable();
InBlock.gif        
private System.ComponentModel.Container components = null;
InBlock.gif        
private XmlDataDocument xmlDataDoc = new XmlDataDocument();
InBlock.gif
InBlock.gif        
public Component1(System.ComponentModel.IContainer container)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            InitializeComponent();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        [DefaultValue(
"")]
InBlock.gif        
public string GetName(Control control)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
string text = (string)_innerTable[control];
InBlock.gif            
if (text == null
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                text 
= string.Empty;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return text;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void SetName(Control c1, string v1)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(_innerTable.Contains(c1))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _innerTable[c1]
=v1;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _innerTable.Add(c1,v1);
ExpandedSubBlockEnd.gif            }

InBlock.gif            c1.KeyPress 
+= new KeyPressEventHandler(c1_KeyPress);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public XmlDataDocument XmlDataDoc
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                xmlDataDoc 
= value;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return xmlDataDoc;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public Component1()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**////
InBlock.gif            
/// Windows.Forms 类撰写设计器支持所必需的
ExpandedSubBlockEnd.gif            
///

InBlock.gif            InitializeComponent();
InBlock.gif
InBlock.gif            
//
InBlock.gif            
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary> 
InBlock.gif        
/// 清理所有正在使用的资源。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        protected override void Dispose( bool disposing )
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if( disposing )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(components != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    components.Dispose();
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
base.Dispose( disposing );
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
组件设计器生成的代码#region 组件设计器生成的代码
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
InBlock.gif        
/// 此方法的内容。
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private void InitializeComponent()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            components 
= new System.ComponentModel.Container();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
IExtenderProvider 成员#region IExtenderProvider 成员
InBlock.gif
InBlock.gif        
public bool CanExtend(object extendee)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// TODO:  添加 Component1.CanExtend 实现
InBlock.gif
            if(extendee is Control && !(extendee is Component1))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return false;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
InBlock.gif        
private void c1_KeyPress(object sender, KeyPressEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if(e.KeyChar == (char)13)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                SendKeys.Send(
"{TAB}");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
       从工具栏中添加这个组件,其容器中所有对应的控件都会增加一个“componet1上的Name” 属性:

       我们可以将额外需要的属性填写在这里,同时我为控件添加了一个回车键跳转,当按回车键时就好像按了TAB键一样。我们既不用自定义这些控件,又不用在容器中添加触发,只要将这些都写到继承了IExtenderProvider接口的组件中就OK了,而对于需要这些属性和方法的控件来说不需要任何的改变。
None.gif          public   bool  CanExtend( object  extendee)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
// TODO:  添加 Component1.CanExtend 实现
InBlock.gif
            if(extendee is Control && !(extendee is Component1))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return false;
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }

       这个方法是IExtenderProvider接口的成员。通过修改它就可以设置我们究竟要为哪种控件添加属性。我这里选择的是Control,所有的控件都会返回true。

None.gif [ProvideProperty( " Name " typeof (Control))]

     Name即是我需要的属性名称。当然这个Name不同于控件本身的Name属性。

None.gif         [DefaultValue( "" )]
None.gif        
public   string  GetName(Control control)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
string text = (string)_innerTable[control];
InBlock.gif            
if (text == null
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                text 
= string.Empty;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return text;
ExpandedBlockEnd.gif        }

None.gif
None.gif        
public   void  SetName(Control c1,  string  v1)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif {
InBlock.gif            
if(_innerTable.Contains(c1))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _innerTable[c1]
=v1;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                _innerTable.Add(c1,v1);
ExpandedSubBlockEnd.gif            }

InBlock.gif            c1.KeyPress 
+= new KeyPressEventHandler(c1_KeyPress);
ExpandedBlockEnd.gif        }

      通过GetName和SetName这两个方法即可对扩展的属性内容进行操作。_innerTable是一个HashTable。在Get的事后可以像属性一样为其设置默认值,但是Set是不可以的。另外在Set时除了设置其值外还可以添加事件。
      使用这种方法我们可以减少不必要的自定义控件的数目,移植起来也更加方便。我原来参与的项目中自定义控件有40多个,其中一部分就属于添加一个属性就要一个自定义控件的情况,因为一个属性,就要为其自定义对应的textbox、combobox、checkbox等等,让人觉得很是不甘心... 通过这种方法就可以给所有符合要求的控件添加同一的属性,管理起来也很便捷。
      这种方法的缺点就是没有继承来得灵活,如果添加的属性不是“大而全”的那种或者有比较复杂的控制关系,还是继承控件比较好用一些吧

转载于:https://www.cnblogs.com/aiyagaze/archive/2006/09/08/498370.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值