下面是该 TreeView 的简单的 Markup:
<
asp:TreeView
ID
="tvCategories"
runat
="server"
CssSelectorClass ="SimpleEntertainmentTreeView"
ExpandDepth ="FullyExpand"
OnSelectedNodeChanged ="tvCategories_SelectedNodeChanged"
OnAdaptedSelectedNodeChanged ="tvCategories_SelectedNodeChanged"
/>
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);
}
}
}
{
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();
}
}
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);
}
}
}
{
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 控件工具包后,有其他控件的事件不触发的情况,可以这样来解决。