技术开发 频道

Tomcat 5集群中的SESSION复制一

    有人说:我要响应事件

    客户端的Behavior除了属性之外还有各种事件——例如CalendarBehavior的shown事件,它会在日历被打开之后触发。利用事件我们就可以在合适的时候执行特定的代码,获得丰富的功能。在服务器端标记属性然后输出至客户端早已众人皆知,那么我们可以在服务器端指定客户端的事件吗?

    以前不行,不过现在已经可以了。在上一个版本AjaxControlToolkit中新增了和属性差不多的支持功能。现在AjaxControlToolkit中包含了一个ExtenderControlEventAttribute类,它的作用就是在服务器端标记某个属性,使它与某个客户端的事件对应。这样我们就可以在服务器端设置客户端某个事件的响应方法,我们只需要保证那个方法存在并且逻辑正确即可。

    例如,我们这次使用CaledarExtender作为示例:

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<ajaxToolkit:CalendarExtender runat="server" TargetControlID="TextBox1"
OnClientShown="onShownHandler"/>
<textarea id="TraceConsole" cols="50" rows="10"></textarea>
<script language="javascript" type="text/javascript">
function onShownHandler(sender, args)
{
Sys.Debug.trace("Calendar shown.");
}
</script>

    目前我在服务器端的CalendarExtender中指定了OnClientShown属性,于是在页面上就出现了如下的JavaScript代码:

Sys.Application.add_init(function()
{
$create(
AjaxControlToolkit.CalendarBehavior,
{"id":"ctl02"},
{"shown":onShownHandler},
null,
$get("TextBox1"));
});

    $create方法的第三个参数是响应事件方法的集合,其中onShownHandler被作为shown事件的响应方法。因此,在每次Calendar被展开之后onShownHandler方法都会被执行,于是在页面上的TextArea中就会显示出“Calendar shown.”的字样。
    服务器端OnClientShown属性和客户端shown事件的映射关系是由CalendarExtender中以下代码决定的:

[DefaultValue("")]
[ExtenderControlEvent]
[ClientPropertyName("shown")]
public virtual string OnClientShown
{
get { ... }
set { ... }
}

    ExtenderControlEventAttribute标记表明该属性将会映射到客户端Behavior的某个事件,而ClientPropertyNameAttribute标记则会接受一个参数,表明具体是哪个事件(如果不标记的话,则使用和属性同名的事件)。

    一切就是这么简单……

    ……只可惜并非每个Extender都那么友好
    例如,HoverMenuExtender。话说HoverMenuBehavior也有事件,例如showing和shown。可惜的是,由于ExtenderControlEventAttribute类和它的功能出现的比较晚,早期版本中出现的控件都没有这个功能。可能在新发布的AjaxControlToolkit中会慢慢地为它们补充这些功能,不过现在还是要响应Behavior的事件啊,是不?

    在《分》文中,我演示了如何在客户端操作单个ModalPopupBehavior,虽然没有使用事件,但是我们既然可以操作那个Behavior对象了,为它添加一个Event Handler难道还不简单吗?不过似乎有朋友结合基于模板反复的控件(例如Repeater)与AjaxControlTookit中控件的时遇到了阻碍——这下子出现了多个Behavior对象,又该如何设置每一个的BehaviorID,又该如何操作每一个Behavior对象呢?要知道,Repeater在页面上最终会反复多少次可能也无法轻易得知(或使用)啊。

    例如,我们结合Repeater控件和HoverMenuExtender来使用:

<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<a id="link" runat="server">Hover on me!</a>
<asp:Panel runat="server" ID="tooltip" style="display:none;
border:solid 1px black; padding:5px; background-color:Yellow; width:100px">
Loading...
</asp:Panel>
<ajaxToolkit:HoverMenuExtender runat="server" ID="hoverMenu"
TargetControlID="link" PopupControlID="tooltip" PopupPosition="Right" />
</ItemTemplate>
<SeparatorTemplate>
<hr />
</SeparatorTemplate>
</asp:Repeater>

    根据上面的代码,当鼠标指向每个<a />元素时,将会出现一个浮动的标签,其中显示Loading字样。 但是如果我们要在每个区域显示出来之后访问一个WebService方法,并将得到的结果显示在浮动的区域内,又该怎么做呢?很显然,我们必须响应每个HoverMenuBehavior对象的shown事件。于是我们可以这样做:

<script language="javascript" type="text/javascript">
function onShownHandler(sender, args)
{
HoverMenuService.GetContent(onSuccess, null, sender.get_popupElement());
}

function onSuccess(result, tooltip)
{
tooltip.innerHTML = result;
}
</script>

<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<a id="link" runat="server">Hover on me!</a>
<asp:Panel runat="server" ID="tooltip"
style="display:none; border:solid 1px black; padding:5px; background-color:Yellow; width:100px;">
Loading...
</asp:Panel>
<ajaxToolkit:HoverMenuExtender runat="server" ID="hoverMenu"
TargetControlID="link" PopupControlID="tooltip" PopupPosition="Right" />

<script language="javascript" type="text/javascript">
Sys.Application.add_load(function(sender, args)
{
if (args.get_isPartialLoad()) return;
var behaviorId = '<%# (Container.FindControl("hoverMenu") as HoverMenuExtender).BehaviorID %>';
$find(behaviorId).add_shown(onShownHandler);
})
</script>
</ItemTemplate>
<SeparatorTemplate>
<hr />
</SeparatorTemplate>
</asp:Repeater>

0
相关文章