CSS 控件适配器工具包对事件处理的 Bug 以及修正办法

今天做一个东西,用了最近刚出来的 CSS 控件适配器工具包,对我的 TreeView 进行定制,结果发现 OnSelectedNodeChanged 事件不工作

下面是该 TreeView 的简单的 Markup:

<asp:TreeView ID="tvCategories" runat="server"
    CssSelectorClass
="SimpleEntertainmentTreeView"
    ExpandDepth
="FullyExpand" 
    OnSelectedNodeChanged
="tvCategories_SelectedNodeChanged"
    OnAdaptedSelectedNodeChanged
="tvCategories_SelectedNodeChanged"        
/>

这个例子我是根据 CSS 控件工具包发布的程序例子模仿来写的。我们注意到,在 TreeView 的属性中,多了几个属性。
这里跟事件相关的是 OnAdaptedSelectedNodeChanged 属性。
追踪代码,发现 CSS 适配器工具包中的类,对被适配的控件的每一个事件,都添加了一个 "OnAdapted" 字样的前缀,然后通过反射找到并调用当前的页面类型中对应的处理方法。其代码如下:

(WebControlAdapterExtender.cs 中)
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 
= AdaptedControl.Page.GetType().GetMethod(delegateName);
        
if (method != null)
        {
            
object[] args = new object[2];
            args[
0= AdaptedControl;
            args[
1= e;
            method.Invoke(AdaptedControl.Page, args);
        }
    }
}

OK, 看到这里问题明朗了。我们通常在页面中定义的事件处理函数会是 protected 的。比如:

protected void tvCategories_SelectedNodeChanged(object sender, EventArgs e) {
    Response.Write(
"selected");
    
if (rlistOpType.SelectedValue == "Edit") {
        LoadCurrentCategoryData();
    }
}

很明显 CSS 控件工具包的这个源码对这个反射调用的写法疏忽了。解决的办法也很简单,将上述代码改成:

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 
= AdaptedControl.Page.GetType().GetMethod(delegateName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        
if (method != null)
        {
            
object[] args = new object[2];
            args[
0= AdaptedControl;
            args[
1= e;
            method.Invoke(AdaptedControl.Page, args);
        }
    }
}

如果你也发现使用了 CSS 控件工具包后,有其他控件的事件不触发的情况,可以这样来解决。

posted on 2006-09-26 18:02  NeilChen  阅读(1511)  评论(3编辑  收藏  举报

导航