使用手风琴控件工具包作为模型构建 AJAX 滚动条控件






4.81/5 (9投票s)
本文将向您展示创建类似 AJAX Control Toolkit 的控件并非难事
引言
几周前,我创建了一个DHTML控件,该控件基于在www.dynamicdrive.com上发布的DHTML。它是一个数据绑定控件,这次经历很愉快。我不得不仔细研究了精彩的《Developing Microsoft ASP.NET Server Controls and Components》,学到了很多新东西。但是,在我开始阅读AjaxControlToolkit并分析其代码后,我意识到有一个更简单、更优雅的方法可以实现同样的事情。
背景
该控件基本上显示一些HTML,显示的HTML会淡入淡出,然后被另一个替换。该控件需要是模板化的,并且能够数据绑定。这个需求最理想的基础是AjaxControlToolkit的Accordion控件。它是比较复杂的控件之一,但它包含了我所需的一切。我使用的Animation Extender的淡入淡出效果实际上是最简单的之一,但它仍然为我们提供了深入研究AJAX这一领域的绝佳方式。
使用代码
您可以将滚动控件用作全功能的数据绑定控件,也可以在代码中以声明式或编程方式输入要滚动的内容。以下是步骤:
- 创建一个支持AJAX的网站
- 在
Scroller
控件的bin文件夹中添加对Scroller
和AjaxControlToolkit
程序集的引用 - 在网页中注册
Scroller
<%@ Register Assembly="Scroller" Namespace="AjaxScroller" TagPrefix="cc1" %>
- 将
Scroller
添加到页面<cc1:scroller id="Sc1" runat="server" contentcssclass="ScrollerPaneStyle" cssclass="ScrollerStyle"> <cc1:scroller>
- 添加
<Panes>
标签 - 根据需要添加任意数量的
Scroller
窗格<cc1:ScrollerPane runat="server" ID="p1"> <Content> Some text to be scrolled <br /> </Content> </cc1:ScrollerPane>
如果您想将滚动控件绑定到数据源,代码应如下所示:
<cc1:Scroller ID="Scroller2" runat="server" DataSourceID="SqlDataSource1"
CssClass="ScrollerStyle" ContentCssClass="ScrollerPaneStyle" >
<Panes></Panes>
<ContentTemplate>
<h2>The description of categorie <%# Eval("CategoryName") %>
<br /></h2>
<%# Eval("Description")%>
</ContentTemplate>
</cc1:Scroller>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="
<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT * FROM [Categories]">
</asp:SqlDataSource>
此Scroller
已绑定到Northwind Categories的描述字段(您需要更改web.config中的连接字符串)。
Scroller
最有趣的属性包括:
TransitionDuration
– 窗格之间的淡入淡出持续时间(默认为1000毫秒),FramesPerSecond
– 默认值为30,以及ContentCssClass
– 定义要滚动内容的样式。
Control
Scroller
不是一个扩展控件。相反,它内部使用一个扩展器来扩展其行为。如我之前所说,该控件以Accordion AjaxcControlToolkit控件为模型。我不会深入解释这个控件,因为它需要比一篇文章更多的篇幅,但我会简要解释所有组件类和最有趣的要点。Accordion控件是创建模板化数据绑定控件的良好模型,并且大部分模式是通用的。我只删除了我不需要的部分(Header模板),添加了一些东西(额外的div,这样淡入淡出就不会影响控件的边框,如果存在的话),并且内部的扩展器JavaScript不得不完全更改。我没有删除与事件相关的类,因为在未来的场景中,我可以快速轻松地使用它们。为了避免混淆代码,ScrollerCommandEventArgs.cs和ScrollerItemEvent.cs未被使用,但如果您想添加一些额外功能,它们就在那里。
类
ScrollerContentPanel
这是一个内容窗格,其中将实例化模板。它遵循数据绑定模式,与AccordationContentPanel
唯一的区别是InVisible
属性,它会将窗格(div)的显示样式设置为“none
”或“block
”。创建控件时,所有窗格都是不可见的,可见性在AjaxScrollerExtender.js中控制。如我所说,有一个OnBubbleEvent
重写,虽然未使用,但为未来保留。这个窗格将由AJAX扩展器实际滚动(淡入淡出)。
ScrollerPane
这是ScrollerContentPane
的容器,它有一个模板 – Content
,该模板在ScrollerContentPane
成员 – ContentContainer
中实例化。最初,Accordion控件还有一个模板 – Header
,这对于我们的Fading Scroller是不需要的。这个控件中有趣的一点是,通过重写RenderBeginTag/RenderEndTag
,它实际上不渲染开始/结束标签。
ScrollerPaneCollection
这是所有ScrollerPanes
的集合,它实现了IList
和IEnumerable
。除了包含对象的类型外,我没有更改这个类中的任何内容。
Scroller
这是所有类中最有趣的一个。控件的大部分是模板化、数据绑定控件的标准代码。我想强调的一点是——如何使用扩展器来扩展你的控件!在此之前,让我们先解释用于扩展Scroller
的实际扩展器。扩展器类的名称是AjaxScrollerExtender
。AjaxScrollerExtender
仅定义了扩展器的属性,而AjaxScrollerDesigner
在设计时对控件进行简单的表示。我将展示完整的AjaxScrollerBegaviour.js代码,其中包含注释,可以帮助您理解它。
Type.registerNamespace('AjaxScroller');
AjaxScroller.AjaxScrollerBehavior = function(element)
{
AjaxScroller.AjaxScrollerBehavior.initializeBase(this, [element]);
// The this._framesPerSecond is used to tune the animation to
// perform well depending on the type of effect being used
// and the number of accordion panes, etc.
this._framesPerSecond = 30;
// The this._duration - how long each fading will last
this._duration = 1;
// The this._panes ScrollingPanes corresponds with
// ScrollingPane from the Scroller control
this._panes = [];
// The this._currentPane is needed to change the content of the
// current fading div
this._currentPane = 0;
// This extender uses composite animation - FateIn and FadeOut.
// I didn't use Pulse animation because I got an error in Firefox.
// I don't know if that is that a bug or not, but I had to
// simulate Pulse with FadeIn and FadeOut.
// The this._fadeAnimation is the composite serial animation,
// this._fadeIn and this._fadeOut are single animations.
this._fadeAnimation = null;
this._fadeIn = null;
this._fadeOut = null;
// The this._hoverOverHendler and this._endedHandler are used to pause,
// restart animation
this._hoverOverHendler = null;
this._hoverOutHendler = null;
// The this._endedHandler is used to change the content to animate,
// and restart the animation
this._endedHandler = null;
// this._autoSize = 0;
}
AjaxScroller.AjaxScrollerBehavior.prototype =
{
initialize : function() {
AjaxScroller.AjaxScrollerBehavior.callBaseMethod(this, 'initialize');
// The structure of the HTML is:
// <div id="Scroller1a" style="overflow:hidden;overflow-x:auto;">
// <div>
// <div> content1 </div>
// <div> content2 </div>
// .....
// </div>
// </div>
// According to the structure, the following code populates
// the panes array.
var e = this.get_element();
var firstchildren = e.childNodes;
for (var i = 0; i < firstchildren.length; i++) {
var child = firstchildren[i];
if (child.nodeType == 1) {
firstDiv = child;
break;
}
}
var children = firstDiv.childNodes;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (child.nodeType == 1) {
Array.add(this._panes, child);
}
}
if (this._panes.length > 0)
{
// Here, we create the animation.
this._fadeIn = new AjaxControlToolkit.Animation.FadeInAnimation
(firstDiv, this._duration, this._framesPerSecond, 0, 1, true);
this._fadeOut = new AjaxControlToolkit.Animation.FadeOutAnimation
(firstDiv, this._duration, this._framesPerSecond, 0, 1, true);
this._fadeAnimation =
new AjaxControlToolkit.Animation.SequenceAnimation
(firstDiv, this._duration, this._framesPerSecond,
[this._fadeIn, this._fadeOut], 1);
// When the simulated Pulse finishes, switch the visible div,
// and start new animation.
this._endedHandler = Function.createDelegate(this, this._switchDiv);
this._fadeAnimation.add_ended(this._endedHandler);
//If user hovers over the div, stop the animation.
this._hoverOverHendler = Function.createDelegate(this, this._hoverOver);
this._hoverOutHendler = Function.createDelegate(this, this._hoverOut);
$addHandlers(e, {
mouseover: this._hoverOverHendler,
mouseout: this._hoverOut,
focus: this._hoverOverHendler,
blur: this._hoverOut
}, this);
// Set the first visible div.
this._panes[this._currentPane].style.display = "block";
// Let's start!
this._fadeAnimation.play();
}
},
// Clean the handlers we created.
dispose : function()
{
if (this._endedHandler)
{
this._fadeAnimation.remove_ended(this._endedHandler);
this._endedHandler = null;
}
$clearHandlers(this.get_element());
AjaxScroller.AjaxScrollerBehavior.callBaseMethod(this, 'dispose');
},
// Cycle through the panes and set the visibility for the current.
// Play the animation for the current.
_switchDiv : function()
{
var currentPane = this._panes[this._currentPane];
currentPane.style.display = "none";
//Sys.Debug.fail("u pr");
this._currentPane++;
if (this._currentPane == this._panes.length) this._currentPane = 0;
var nextPane = this._panes[this._currentPane];
nextPane.style.display = "block";
this._fadeAnimation.play();
},
_hoverOver: function()
{
this._fadeAnimation.pause();
},
_hoverOut: function()
{
// The play method doesn't work good after Pause – is it a bug?
// Just Stop, and Play will fix the problem.
this._fadeAnimation.stop();
this._fadeAnimation.play();
},
.....
所以,回到重点——你如何使用这个扩展器来扩展你的控件!只需在你的控件中声明一个private
AjaxScrollerExtender
属性,然后在CreateChildControls
中重写它,为其分配一个ID,并将TargetControlID
设置为你的控件ID。
_extender = new AjaxScrollerExtender();
_extender.ID = ID + "_ScrollerExtender";
_extender.TargetControlID = ID;
if (!this.DesignMode)
Controls.AddAt(0, _extender);
关注点
本文的主要观点是如何轻松创建功能齐全的AJAX控件。这个控件可以很容易地扩展,使用更复杂的AJAX动画来创建各种文本效果。例如,添加颜色动画只需几行代码即可完成。AJAX Control Toolkit的Animation Extender为您提供了非常强大的基础,唯一的限制是您的创造力。