65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (9投票s)

2007年5月25日

CPOL

4分钟阅读

viewsIcon

76797

downloadIcon

551

本文将向您展示创建类似 AJAX Control Toolkit 的控件并非难事

Screenshot - AjaxScroller.gif

引言

几周前,我创建了一个DHTML控件,该控件基于在www.dynamicdrive.com上发布的DHTML。它是一个数据绑定控件,这次经历很愉快。我不得不仔细研究了精彩的《Developing Microsoft ASP.NET Server Controls and Components》,学到了很多新东西。但是,在我开始阅读AjaxControlToolkit并分析其代码后,我意识到有一个更简单、更优雅的方法可以实现同样的事情。

背景

该控件基本上显示一些HTML,显示的HTML会淡入淡出,然后被另一个替换。该控件需要是模板化的,并且能够数据绑定。这个需求最理想的基础是AjaxControlToolkit的Accordion控件。它是比较复杂的控件之一,但它包含了我所需的一切。我使用的Animation Extender的淡入淡出效果实际上是最简单的之一,但它仍然为我们提供了深入研究AJAX这一领域的绝佳方式。

使用代码

您可以将滚动控件用作全功能的数据绑定控件,也可以在代码中以声明式或编程方式输入要滚动的内容。以下是步骤:

  1. 创建一个支持AJAX的网站
  2. Scroller 控件的bin文件夹中添加对Scroller AjaxControlToolkit 程序集的引用
  3. 在网页中注册Scroller

    <%@ Register Assembly="Scroller" Namespace="AjaxScroller" 
                            TagPrefix="cc1" %>    

  4. Scroller 添加到页面

    <cc1:scroller id="Sc1" runat="server" 
        contentcssclass="ScrollerPaneStyle" 
            cssclass="ScrollerStyle">
    <cc1:scroller>    

  5. 添加<Panes> 标签
  6. 根据需要添加任意数量的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.csScrollerItemEvent.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为您提供了非常强大的基础,唯一的限制是您的创造力。

© . All rights reserved.