代码改变世界

讲座展示:TechEd Europe DEV344 - ASP.NET AJAX Control Toolkit(上)

2006-11-15 18:23 Jeffrey Zhao 阅读(...) 评论(...) 编辑 收藏

从现在开始,我会将一些我认为有价值的讲座内容介绍给大家,尤其会将其中的经典示例里以Step by Step的形式演示一下。可能这些讲座的不会非常深入,但是能保证其质量非常高,因此都是不可多得的学习内容。而通过类似于Hands on Lab的一步一步实践,也能让大家对于某项技术有着更加牢固的理解。另外,由于某些讲座的演示的部署会比较复杂,我在这里也会比较详细地对这些演示的部署方式进行说明,方便大家在使用演示项目的同时能够动手进行修改,加深理解。对于难以接受英文讲座的朋友也可以通过我的文章了解讲座的精彩内容。

除非特别注明,文章里使用的内容,图片以及源代码均来源于演讲者本人或者官方发布的讲座内容。

 

讲座内容

这次我选择的讲座内容是最近在TechEd 2006 Europe中Shawn Burke的讲座“ASP.NET AJAX Control Toolkit Unleashed: Creating Rich Client-Side Controls and Components”。Shawn Burke是微软.NET Developer Platform总监。这个讲座的PPT和演示代码的下载地址已经由他本人公布在他的Blog上本地下载)。另外,在MSDN's Showtime上也已经有了这个讲座的完整视频

此次讲座的内容主要是对于ASP.NET AJAX Control Toolkit进行简单的介绍,展示了Extender控件是如何帮助ASP.NET开发人员简单地将丰富的用户体验集成到他们的Web应用程序中。在这次讲座里将看到应该如何在您的应用中使用ASP.NET AJAX Control Toolkit中的组件,并且了解开发人员是如何方便地开发一个APS.NET AJAX Extender的。

此次讲座分为两部分:“ASP.NET AJAX Control Toolkit介绍和使用”以及“开发一个Extender控件”。本文将对于该讲座的第一部分进行讲述,并且对其第一个演示进行分析。

ASP.NET AJAX Control Toolkit开发团队使用了敏捷方法,能够尽早地接受到用户反馈。整个项目的开发过程非常透明,使用户很好能参与进来,并且完全开放各种资源(例如bug数据库,源代码等),这种做法使得项目能在相对较早的阶段就能拥有较高的质量。ASP.NET AJAX Control Toolkit的目标是为了能够让服务器端开发人元非常方便地将AJAX特性加入他们的站点中,同时也能使客户端开发人员能够比较轻易地写出良好封装容易复用的AJAX组件。这种良好的AJAX组件开发和使用方式能够使AJAX特性更加容易被各种类型的开发人员所接受。另外,ASP.NET AJAX Control Toolkit也创造性地使用了一种透明的,并且由社区驱动的开发模型。

ASP.NET AJAX Control Toolkit包含许多组件,能够使ASP.NET开发人员方便地为自己的应用增加客户端的UI效果。关于这一点Scott Guthrie提到过:“Scott Hanselman曾经开玩笑地把这些AJAX控件称作‘作弊’……因为它们能使您在最常用的情况下不用写任何客户端JavaScript代码而获得AJAX特性”。它也是一个能够开发和部署AJAX组件的框架,而这种开源的方式也能将社区和微软强强联手,开发出一套具有最佳实践价值的产品。在开发过程中,会使用3名微软的开发人员组成的小团队和10名左右的外部人员贡献他们的力量。任何人都可以在http://www.codeplex.com中下载到任何时候check-in的代码,不过在开发过程中会使用Microsoft Visual Studio Team Foundation Server的功能进行控制,只有拥有一定权限的参与者才能对代码进行更新。

下面这幅图描述了ASP.NET AJAX Control Toolkit的技术组成(点击小图可查看大图):

我们通过这幅图看到ASP.NET AJAX Control Toolkit是如何结合ASP.NET AJAX的。在这些技术的核心,是ASP.NET AJAX Extentions和ASP.NET AJAX Library,它们刚在周一发布了Beta 2,而且会在下个月将发布最终版本,并且会集成进下一版本的.NET Framework(Shawn原话)。图中黄色部分表示了在Atlas里而不是核心的功能,我们称之为Value-Add和CTP,它们也能从ASP.NET AJAX网站下载。蓝色部分表示了Toolkit,是个由社区驱动的项目,分为Server端组件和Client端组件两部分。这就是我们发布各种Toolkit功能的模型,我们用了各种方法使用户参与进来,让项目得到及时的大量反馈。

下面这幅图描述了ASP.NET AJAX Control Toolkit的架构(点击小图可查看大图):

我们可以看到ASP.NET Control Toolkit是如何工作的。ASP.NET Control Toolkit不光是基于已有的ASP.NET 2.0和.NET Framework,也使用了ASP.NET Server Extentions和ASP.NET AJAX Library。黄色部分表示了已经存在的ASP.NET 2.0功能基础,而绿色部分表示了由ASP.NET AJAX团队已经建立的核心基础。我们起初在开发Atlas时建立了一部分的组件,通过社区反馈来得知这些组件是否常用。目前已经建立了超过30个组件了。另外为了帮助用户开发自己的组件,我们也建立了Visual Studio 2005的模版。

ASP.NET AJAX Control Toolkit拥有良好的跨浏览器特性,能够良好地支持IE6、IE7、FireFox和Safari等主流浏览器。对于Opera浏览器的支持是一个的目标,我们将会尽可能地对于Opera浏览器进行支持,关于这一点有个好消息:目前只有非常少的功能无法支持了。另外,我们尽力使目前的ASP.NET AJAX框架能够与其它的AJAX框架(例如Prototype,dojo)进行良好地集成,而不会引发冲突。在这里我们会提到三种组件:Control、Extender和Behavior。其中Control就是传统的控件,它是ASP.NET AJAX Control Toolkit的表现方式;Extender组件是一些服务器端代码,它使客户端的功能得到执行;最后则是Behavior组件,它是使用JavaScript编写的客户端核心功能。

在使用ASP.NET AJAX Control Toolkit进行页面开发时,能够很轻易地为已有站点的功能进行增强,当然新建一个站点就更不在话下了。目前ASP.NET AJAX Control Toolkit包含了超过30个具有AJAX特性的组件,您无需掌握JavaScript就能很轻易地使用它们。您能够在设计期以拖放的形式进行开发,而且这一点在Visual Studio "Orcas"中会有更好的体现。在部署时,您也只需将程序集简单地复制到站点的Bin目录下即可,而开发源代码的特性也使得这些组件能够很方便地让用户针对自己的项目自定义其中的任何部分,包括添加新的功能和修补其中的Bug。

 

讲座演示

这个演示的代码可以在压缩包“TechEd_Dev344.zip”的“\Demos\ToolkitBasics\WebSite”目录下找到,没有任何复杂的部署方式,只需要装有ASP.NET AJAX Beta 2即可。

我们来简单看一下如何在已有的站点中使用Toolkit。首先打开“Before.aspx”文件,我们可以看到如下的页面(点击小图可查看大图):

这是个图片展示网站。这个站点叫做“Image Flix”,它会搜索服务器中收藏的图片,并以表格的形式展示出来。我们可以看到一些分类,也有搜索框。当点击某个分类时,这个示例会随机选择一些图片,不过您可以想象这是在浏览一个图片分类。每一个次点击都会引发一个Post Back,这是个标准的ASP.NET应用程序。如果我们要把Toolkit运用到我们的站点中,我们首先要做的就是为站点添加一个Microsoft.web.Extensions程序集的引用,这个是Microsoft ASP.NET AJAX的程序集。然后需要添加一个AjaxControlToolkit的引用。如图(点击小图可查看大图):

下一步要做的就是改变Web.config中的内容。最好的方法是新建一个ASP.NET AJAX站点,然后查看它的Web.config文件的内容,然后将内容合并到您的Web.config文件中。您现在能够在现在Web.config文件中看到所有的Section定义:

Configuration Sections - Web.config文件
<configSections>
  <sectionGroup name="microsoft.web" type="...">
    <sectionGroup name="scripting" type="...">
      <sectionGroup name="webServices" type="...">
        <section name="jsonSerialization" type="..." requirePermission="false" />
        <section name="profileService" type="..." requirePermission="false" />
        <section name="authenticationService" type="..." requirePermission="false" />
      </sectionGroup>
    </sectionGroup>
  </sectionGroup>
</configSections>

 

还有一些Tag前缀和Tag映射的定义:

Tag Prefix and Tag Mapping Definitions - Web.config文件
<pages>
  <controls>
    <add tagPrefix="asp" namespace="Microsoft.Web.UI" assembly="..."/>
    <add tagPrefix="asp" namespace="Microsoft.Web.UI.Controls" assembly="..."/>
  </controls>
  <tagMapping>
    <add tagType="..." mappedTagType="..."/>
    <!-- other tag mapping -->
  </tagMapping>
</pages>

 

当您将这些设置好以后,就可以使用ASP.NET AJAX了。在这个示例中我们已经添加了ASP.NET AJAX的功能(DemoStart.aspx文件)。我们使用了UpdatePanel,UpdatePanel是ASP.NET AJAX的核心控件,它使我们能够在页面不完全加载的情况下,使页面的一部分内容得以刷新:

UpdatePanel - DemoStart.aspx文件
<asp:UpdatePanel ID="up1" runat="server">
    <ContentTemplate>
        <asp:DataList ID="DataList1" runat="server" RepeatColumns="5">
            <ItemTemplate>
                <asp:Panel ID="Panel1" runat="server" Height="100px" Width="100px" CssClass="panel">
                    <asp:Image ID="Image1" runat="server"
                        ImageUrl='<%# ImageFromFile((string)Eval("FileName"), 100, 100) %>' />
                </asp:Panel>
                <!-- TODO: HoverMenu and Panel -->
            </ItemTemplate>
        </asp:DataList>
    </ContentTemplate>
</asp:UpdatePanel>

 

现在,当您点击右边的类别时,可以发现左边的图片展示框的更新,但是页面并没有重新加载。我们的示例将从这里开始,它已经提供了一个不错的用户体验(老赵:您可以打开DemoStart.aspx查看效果)。

我们第一件需要做的事情就是在页面顶端添加AjaxControlToolkit的注册标签,这样才能够使用Toolkit的功能。这只是一个简单的Tag,引用了AjaxControlToolkit的程序集,并定义了Namespace,然后给定了一个Tag前缀,在这里我们使用“ajaxToolkit”,当然您也可以使用任意的前缀。如下:

Register ASP.NET AJAX Control Toolkit
<!-- TODO: Register -->
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>

 

首先我们需要做的就是增强我们页面下方的搜索框,我们这里使用TextBoxWatermarkExtender,它允许我为页面中的文本框增加水印效果,可以告诉用户在这个文本框中应该输入什么内容。这个很容易做到:

TextBoxWatermarkExtender
<asp:Panel ID="SearchGroup" runat="server" CssClass="group">
Search:<br />
    <asp:TextBox ID="Search" runat="server" Width="120" /><br />
    <asp:Button ID="Submit" runat="server" Text="Go" />
    <!-- TODO: TextBoxWatermark -->
    <div>
        <!-- div works around browser bug for margin-bottom collapse -->
        <ajaxToolkit:TextBoxWatermarkExtender ID="TextBoxWatermarkExtender2" runat="server"
            TargetControlID="Search" WatermarkText="Type query" WatermarkCssClass="watermark" />
    </div>
</asp:Panel>

 

当我们将一个Extender添加到页面中之后,看到几个属性,其中最重要的属性就是TargetControlID,它指定了Extender需要操作的控件的ID,在这里我们就指定那个搜索用的文本框。在设计模式里我们可以在PropertyGrid中看到这个文本框有了一个附加的属性。如图(点击小图可查看大图):

这里每一个属性都与Extender本身相对应。WatermarkText表示在水印效果时文本框内显示的文本。那么什么是WatermarkCssClass属性呢?WatermarkCssClass是我们希望在水印效果时,应用在那个控件上的CSS类。如图:

我们再回到页面。我们接着再为每个选择图片类别的Panel各添加一个CollapsiblePanelExtender。代码如下:

CollapsiblePanelExtender
<asp:Panel ID="PopularGroup" runat="server" CssClass="group">
    <asp:Panel ID="PopularHeader" runat="server" Style="cursor: pointer">
        <asp:Label ID="PopularLabel" runat="server" Text="Popular Groups" />
    </asp:Panel>
    <asp:Panel ID="PopularContent" runat="server">
        <asp:LinkButton ID="LinkButton1" runat="server">Pretty images</asp:LinkButton><br />
        <asp:LinkButton ID="LinkButton2" runat="server">Cool images</asp:LinkButton><br />
        <asp:LinkButton ID="LinkButton3" runat="server">Neat images</asp:LinkButton><br />
        <asp:LinkButton ID="LinkButton4" runat="server">Silly images</asp:LinkButton><br />
    </asp:Panel>
    <!-- TODO: CollapsiblePanel -->
    <ajaxToolkit:CollapsiblePanelExtender ID="CollapsiblePanelExtender1" runat="server"
        TargetControlID="PopularContent" TextLabelID="PopularLabel"
        CollapsedText="Popular Groups ▼" ExpandedText="Popular Groups ▲"
        CollapseControlID="PopularHeader" ExpandControlID="PopularHeader" />
</asp:Panel>

 

CollapsiblePanelExtender能让我们指定一个Panel,使它能够收缩和展开,如图:

请看CollapsiblePanelExtender的属性。TargetControlID在这里为PopularContent,表示Extender会操作这个Panel。TextLabelID为NewLabel,我们指定了一个Label,在展开和收缩两种不同状态时会修改这个Label的文字。然后我们通过定义CollapsedText和ExpandedText属性决定了在收缩和展开两种状态下显示在Label中的文字。我们这里使用了Unicode字符来显示那个箭头,当然您也可以在这里使用图片。

下面我们要添加一个查看大图片的功能。我们在这里可以使用HoverMenuExtender来实现。HoverMenuExtender的功能是当用户将鼠标移动到某个元素时,弹出另外一个UI元素。代码如下:

HoverMenuExtender
<asp:DataList ID="DataList1" runat="server" RepeatColumns="5">
    <ItemTemplate>
        <asp:Panel ID="Panel1" runat="server" Height="100px" Width="100px" CssClass="panel">
            <asp:Image ID="Image1" runat="server"
                ImageUrl='<%# ImageFromFile((string)Eval("FileName"), 100, 100) %>' />
        </asp:Panel>
        <!-- TODO: HoverMenu and Panel -->
        <ajaxToolkit:HoverMenuExtender ID="HoverMenuExtender1" runat="server"
            TargetControlID="Panel1" OffsetX="50" OffsetY="50" PopupControlID="Panel2"
            HoverCssClass="panelHover" DynamicControlID="Label1"
            DynamicServiceMethod="GetDetails" DynamicContextKey='<%# Eval("FileName") %>' />
        <asp:Panel ID="Panel2" runat="server" CssClass="popup" Style="display: none">
            <asp:Label ID="Label1" runat="server" />
        </asp:Panel>
    </ItemTemplate>
</asp:DataList>

 

对于HoverMenuExtender来说,TargetControlID为响应鼠标移动的控件,在这里就是显示图片的Panel1。PopupControlID指定了弹出的控件,因此我们添加Panel2用来作为弹出的UI。另外可以发现,在HoverMenuExtender的DynamicServiceMethod属性设定了GetDetails方法,而DynamicContextKey则设定了图片名。HoverMenuExtender提供了这样一个功能,比如在UI显示之前从服务器端更新内容,这样我们就能控制在UI中显示的内容。因此我们会在页面中添加一个静态方法:

GetDetails方法(定义在After.aspx.cs中)
[System.Web.Services.WebMethod]
[Microsoft.Web.Script.Services.ScriptMethod()]
public static string GetDetails(string contextKey)
{
    foreach (ImageInfo ii in data)
    {
        if (ii.FileName == contextKey)
        {
            return string.Format(
                "<img src='{0}'><br/>Name: {1}<br/>Dimensions: {2} pixels<br/>Size: {3} bytes",
                ImageFromFile(ii.FileName, 300, 250), ii.Name, ii.Dimensions, ii.Size);
        }
    }
    return string.Format("[Missing image: {0}]", contextKey);
}

 

现在重新打开页面可以发现,当鼠标指向图片时,将会弹出一个UI,其中显示了大图及其详细信息。如下(点击小图可查看大图):

现在还有一个比较让用户迷惑的就是,在点击分类中的每一项时,左边的图片需要等一段时间才能刷新。我们也需要提高这里的用户体验。之前我们在页面里使用了UpdatePanel,我们现在为它添加动画,以提醒用户UpdatePanel正在更新,所以我们在这里使用另一个组件:UpdatePanelAnimationExtender:

UpdatePanelAnimationExtender
<!-- TODO: UpdatePanelAnimation -->
<ajaxToolkit:UpdatePanelAnimationExtender runat="server"
    ID="UpdatePanelAnimationExtender1" TargetControlID="UpdatePanel1">
    <Animations>
        <OnUpdating>
            <FadeOut AnimationTarget="Fader" MinimumOpacity="0.2" Duration="0.25" />
        </OnUpdating>
        <OnUpdated>
            <FadeIn AnimationTarget="Fader" MinimumOpacity="0.2" Duration="0.25" />
        </OnUpdated>
    </Animations>
</ajaxToolkit:UpdatePanelAnimationExtender>

 

在这里,TargetControlID指定的是UpdatePanel1。在这里有一段XML,Toolkit提供了一套完整的动画类库以供客户端使用,它们都完全使用了JavaScript和DHTML编写。现在这段XML的含义是:在UpdatePanel在向服务器端请求数据时会出现淡出效果,而得到数据后会产生淡入的效果。现在当切换类别时就会出现淡出的效果,当更新结束后,图片区域就会淡入。效果如下(点击小图可查看大图):

这种方式使用户能够更清晰地了解到页面正在更新中。正如我刚才提到了,Toolkit提供了一套完整的动画类库,您可以使用各种组合来得到各种效果。在下载Toolkit的站点上,我们提供了4份参考文档来解释Animation的使用,例如SizeAnimation,MoveAnimation,FadeIn/FadeOutAnimation等等,您可以将它们组合起来得到各种有趣的效果。

好,以上就是演示应该如何在已有的站点中使用ASP.NET AJAX Control Toolkit的例子。