对 CSS 控件适配器处理事件的 Bug 进一步修正

本文探讨了CSS控件适配器处理事件的Bug,并提供了一种修改方案,使事件能够在UserControl中处理。通过调整查找方法的方式,解决了在封装控件时遇到的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天我在这个随笔里: http://www.cnblogs.com/RChen/archive/2006/09/26/css_control_adapter_bug.html
描述了 CSS 控件适配器处理事件的 Bug,并且给出了一个简单的修改方法。

今天,当我对昨天的代码重构时,“老同志”又出现了“新问题”。

由于我用的 TreeView 的加载以及一些逻辑都是通用的,很自然的,我想把该 TreeView 封装到一个 UserControl 中,但是,我们注意到 WebControlAdapterExtender 类的源代码中,使用了这样一句代码:

MethodInfo method  =  AdaptedControl.Page.GetType().GetMethod(delegateName);

这里的判断还是太简单了,作者压根没打算让我们能在 UserControl 中处理事件!而这显然是很不妥当的。
这里,我的修改办法是从被适配的控件开始,向它的父级控件依次查找其中是否定义了该方法,如果找到则执行之。代码如下:

public   void  RaiseAdaptedEvent( string  eventName, EventArgs e) {
    
string  attr  =   " OnAdapted "   +  eventName;
    
if  ((AdaptedControl  !=   null &&
        (AdaptedControl.Attributes[attr] 
!=   null &&
        (AdaptedControl.Attributes[attr].Length 
>   0 )) {
        
string  delegateName  =  AdaptedControl.Attributes[attr];
        MethodInfo method 
=   null ;
        Control parent 
=  AdaptedControl;

        
while (parent != null ) {
            method 
= parent.GetType().GetMethod(delegateName, BindingFlags.Public | BindingFlags.NonPublic |
 BindingFlags.Instance);
            
if (method != null
)
                
break
;
            parent 
=
 parent.Parent;
        }

        
        
if  (method  !=   null ) {
            
object [] args  =   new   object [ 2 ];
            args[
0 =  AdaptedControl;
            args[
1 =  e;
            method.Invoke(parent, args);
        }
    }
}

在这里,也许我们会有一个担心,就是如果在控件多个父层次的控件中,定义了同名的处理函数,会不会造成冲突?其优先级又应该是以哪个为最高呢?

其实,这个担心是不必要的。因为该事件引发函数要求符合 "OnAdapted" 前缀开头的规定;而其他 DotNet 内部的控件的事件引发函数,按照规范都是以 "On" 开头,所以冲突的可能性很小。
另外,如果我们在 UserControl,或者 CustomControl (组合式的)中处理该事件时,则应该将这个“适配”操作封装在内部,对外界而言,暴露另一个常规事件即可。如下述代码所示:

我的用户控件 CategoryTree.ascx 中的代码:
< asp:TreeView  ID ="tvCategories"  runat ="server"
    CssSelectorClass
="SimpleEntertainmentTreeView"
    ExpandDepth
="FullyExpand"
    OnSelectedNodeChanged
="tvCategories_SelectedNodeChanged"
    OnAdaptedSelectedNodeChanged
="tvCategories_SelectedNodeChanged"             
/>

在该 UserControl 的后台处理代码中,对事件进行了封装。现在对于该控件的使用者而言,CSS 适配器的操作完全是透明的,只需要处理常规的 OnSelectedNodeChanged 事件:

#region  Events

private   static   object  SelectedNodeChangedEvent  =   new   object ();

public   event  EventHandler SelectedNodeChanged {
    add { Events.AddHandler(SelectedNodeChangedEvent, value); }
    remove { Events.RemoveHandler(SelectedNodeChangedEvent, value); }
}                

protected   virtual   void  OnSelectedNodeChanged(EventArgs e) {
    EventHandler handler 
=  (EventHandler) Events[SelectedNodeChangedEvent];

    
if  (handler  !=   null )
        handler(
this , e);
}

#endregion

///   <summary>
///  this raises an changed event.
///   </summary>
///   <param name="sender"></param>
///   <param name="e"></param>
protected   void  tvCategories_SelectedNodeChanged( object  sender, EventArgs e) {
    OnSelectedNodeChanged(e);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值