zoukankan      html  css  js  c++  java
  • 对 CSS 控件适配器处理事件的 Bug 进一步修正

    昨天我在这个随笔里: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);
    }
  • 相关阅读:
    Spring之IOC、AOP和事务
    Spring Aware接口
    ReentrantLock原理
    基于AnnotationConfigApplicationContext的容器创建过程(Spring Version 5.2.0)
    基于AnnotationConfigApplicationContext的Bean加载过程(Spring Version 5.2.0)
    Future和CompletableFuture
    ThreadLocal原理
    Oracle 11g R2 数据库卸载教程
    Oracle 11g R2 数据库安装教程
    SQL Server 2017数据库卸载教程
  • 原文地址:https://www.cnblogs.com/RChen/p/css_adapter_bugfix_continued.html
Copyright © 2011-2022 走看看