对 CSS 控件适配器处理事件的 Bug 进一步修正
来源:互联网 发布:南风捏脸数据御姐 编辑:程序博客网 时间:2024/04/30 07:52
昨天我在这个随笔里:http://www.cnblogs.com/RChen/archive/2006/09/26/css_control_adapter_bug.html
描述了 CSS 控件适配器处理事件的 Bug,并且给出了一个简单的修改方法。
今天,当我对昨天的代码重构时,“老同志”又出现了“新问题”。
由于我用的 TreeView 的加载以及一些逻辑都是通用的,很自然的,我想把该 TreeView 封装到一个 UserControl 中,但是,我们注意到 WebControlAdapterExtender 类的源代码中,使用了这样一句代码:
这里的判断还是太简单了,作者压根没打算让我们能在 UserControl 中处理事件!而这显然是很不妥当的。
这里,我的修改办法是从被适配的控件开始,向它的父级控件依次查找其中是否定义了该方法,如果找到则执行之。代码如下:
在这里,也许我们会有一个担心,就是如果在控件多个父层次的控件中,定义了同名的处理函数,会不会造成冲突?其优先级又应该是以哪个为最高呢?
其实,这个担心是不必要的。因为该事件引发函数要求符合 "OnAdapted" 前缀开头的规定;而其他 DotNet 内部的控件的事件引发函数,按照规范都是以 "On" 开头,所以冲突的可能性很小。
另外,如果我们在 UserControl,或者 CustomControl (组合式的)中处理该事件时,则应该将这个“适配”操作封装在内部,对外界而言,暴露另一个常规事件即可。如下述代码所示:
我的用户控件 CategoryTree.ascx 中的代码:
在该 UserControl 的后台处理代码中,对事件进行了封装。现在对于该控件的使用者而言,CSS 适配器的操作完全是透明的,只需要处理常规的 OnSelectedNodeChanged 事件:
描述了 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);
}
}
}
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"
/>
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);
}
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);
}
- 对 CSS 控件适配器处理事件的 Bug 进一步修正
- CSS 控件适配器工具包对事件处理的 Bug 以及修正办法
- CSS 控件适配器工具包对事件处理的 Bug 以及修正办法
- 关于TabControl控件的bug修正
- Extjs keyup事件bug修正
- C#的事件处理和自定义事件的进一步理解
- 修正IE下使用CSS属性overflow的bug
- 修正webwork 2.2.7对json的支持的bug
- 修正bug的方法
- CCEditBox的bug修正
- RecycleView的通用适配器BaseQuickAdapter处理item中子控件的点击事件以及cardview卡片阴影
- CSS 控件适配器的菜单样式解释
- CSS 控件适配器的菜单样式解释
- CSS BUG顺口溜,快速牢记CSS的Bug处理方法
- 猫东formValidator对SELECT(单选)控件处理的bug
- 修正XPMenu的两个Bug
- BugFree 的一个 bug 修正
- Subversion分支的Bug修正
- IronPython 源码剖析系列(1):IronPython 编译器
- 产业链产生还需要很久
- Windows 系统右键菜单假死问题解决一例
- TreeViewVisitor: 一个快捷访问 TreeView 控件节点的帮助类
- CSS 控件适配器的菜单样式解释
- 对 CSS 控件适配器处理事件的 Bug 进一步修正
- CSS 控件适配器工具包对事件处理的 Bug 以及修正办法
- 第一个 IronPython 的 ASP.NET 程序
- Anthem.NET 的回调流程图
- 使用 Anthem.NET 的常见回调(Callback)处理方式小结
- Web Application Project for Visual Studio 2005 中如何同步页面和 designer.cs 代码
- ASP.NET 2.0 的 Event Validation
- 状态机学习及对一段 java 代码的改写
- VS 2005 默认浏览器设定以及关于配置的思考