用于管理带图标显示项的列表的 AJAX 图片列表控件
一个受 WinForms 的 ListView 启发并实现了 ASP.NET AJAX Extensions 1.0 的 ASP.NET 服务器控件。
引言
我们的目标是提供一种在浏览器中管理小型项目列表的方法,包括添加和删除项目,其中最终列表可以发布到 ASP.NET 服务器。此功能由一个 `ImageList` 控件完成,该控件受到 WinForms 的 `ListView` 控件的启发。我们的环境是 Windows 和 IIS 上的 ASP.NET 2.0,我们的图像列表使用 ASP.NET AJAX Extensions 1.0,您可以从此处下载并安装。
背景
本文引用了“Memba Velodoc XP Edition”的开源控件,您可以从此处下载(此页面提供了 Codeplex、Google code 和 Sourceforge.NET 的链接),并根据 GPL 许可证分发。这些控件包含本文中使用的图像列表。您可以在此链接实时体验这些控件。
使用代码
在 Visual Studio 2005 中,创建一个新的 ASP.NET AJAX-Enabled Web Site,并添加对包含 `ImageList` 服务器控件的 *Memba.WebControls.XP.dll* 的引用。*Memba.WebControls.XP.dll* 是 Memba Velodoc XP Edition 的一部分。源代码可在上述下载位置获取。
打开 *Default.aspx* 页面,并通过将其添加到工具箱后拖放控件,或直接在现有 `<form>` 标签之间添加以下代码来添加 `ImageList` 服务器控件。
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager" runat="server">
<Scripts>
<asp:ScriptReference Path="~/scripts/Memba.Utils.js" />
</Scripts>
</asp:ScriptManager>
<table border="0" cellpadding="0" cellspacing="5">
<tr>
<td>
<!-- ImageList -->
<mbui:ImageList ID="ImageList1" runat="server"
CssClass="cssList"
ItemCssClass="cssItem"
ItemHoverCssClass="cssItemHover"
ImageCssClass="cssImage"
TextCssClass="cssText"
RemoveCssClass="cssRemove"
RemoveTooltip="Remove from selection"
LinesOfText="2"
Height="92px"
Width="300px">
</mbui:ImageList>
<!-- ImageList -->
</td>
<td align="center">
<input id="txtItem" type="text" value="new item"
style="width:100px;" />
<input id="btnNew" type="button" value="New"
style="width:100px;" /><br />
<input id="btnCopy" type="button" value="Copy >>"
style="width:100px;" /><br />
<asp:Button ID="btnSubmit" runat="server" Text="Submit"
style="width:100px;" OnClick="btnSubmit_Click" />
</td>
<td>
<!-- ImageList -->
<mbui:ImageList ID="ImageList2" runat="server"
CssClass="cssList"
ItemCssClass="cssItem"
ItemHoverCssClass="cssItemHover"
ImageCssClass="cssImage"
TextCssClass="cssText"
RemoveCssClass="cssRemove"
RemoveTooltip="Remove from selection"
LinesOfText="2"
Height="92px"
Width="300px">
</mbui:ImageList>
<!-- ImageList -->
</td>
</tr>
</table>
<textarea id="TraceConsole" cols="100" rows="20"></textarea>
</form>
该表单还包括一个 HTML 文本框(`txtItem`)、两个 HTML 按钮(`btnNew` 和 `btnCopy`)以及一个 ASP.NET 提交按钮(`btnSubmit`)。
您可能需要在页面顶部使用以下语句注册标签前缀
<%@ Register Assembly="Memba.WebControls.XP"
Namespace="Memba.WebControls" TagPrefix="mbui" %>
确保添加对 *Memba.Utils.js* 的脚本引用,该文件包含在 JavaScript 中创建 GUID 所必需的实用函数。
`ImageList` 控件是一个 `DIV`,它嵌入了一系列浮动的 `DIV`,每个 `DIV` 代表一个项目。每个项目 `DIV` 都包含一个图像、一个标签和一个删除图标。在页面 `</head>` 结束标签的正上方添加以下样式
<style type="text/css">
<!--
div.cssList
{
position:fixed;
overflow:auto;
height:92px;
border:1px solid #0F0000;
background-color:#FFFFFF;
clear:both;
}
div.cssItem
{
position:relative;
width:70px;
height:70px;
padding:5px;
margin:5px;
text-align:center;
border:1px solid #FFFFFF;
background-color:#FFFFFF;
float:left;
}
div.cssItemHover
{
position:relative;
width:70px;
height:70px;
padding:5px;
margin:5px;
text-align:center;
border:solid 1px #DCDCDC;
background-color:#FAFAFA;
float:left;
}
img.cssImage
{
height:32px;
width:32px;
border:0px;
}
div.cssText
{
font-family:Arial, Helvetica, sans-serif;
font-size:9px;
white-space:normal;
}
img.cssRemove
{
position:absolute;
top:64px;
left:64px;
height:16px;
width:16px;
border:0px;
z-index:10;
cursor:pointer;
}
//-->
</style>
您的 `ImageList` 控件现在应如下所示
显然,您可以使用服务器端代码设置列表内容。打开名为 *Default.aspx.cs* 的代码隐藏文件,并实现 `Page_Load` 事件处理程序,如下所示
protected void Page_Load(object sender, EventArgs e)
{
//Initialize ImageList1 with a new item
ImageList1.ImageListItemCollection.Add(
new Memba.WebControls.ImageListItem(
Guid.NewGuid().ToString(),
this.ResolveClientUrl("~/images/angel.gif"),
"item #1"
)
);
}
按 F5 运行页面,并检查列表中是否有一个项目。您需要一个图像文件位于上述代码片段中指定的位置。
双击 ASP.NET 提交按钮,并实现 `Click` 事件处理程序,如下所示
protected void btnSubmit_Click(object sender, EventArgs e)
{
//List the content of ImageList1
Response.Write("<strong>ImageList1</strong>");
if (ImageList1.ImageListItemCollection.Count > 0)
{
Response.Write("<ul>");
foreach (Memba.WebControls.ImageListItem objImageListItem
in ImageList1.ImageListItemCollection)
{
Response.Write("<li>" +
objImageListItem.Text + "</li>");
}
Response.Write("</ul>");
}
//List the content of ImageList2
Response.Write("<strong>ImageList2</strong>");
if (ImageList2.ImageListItemCollection.Count > 0)
{
Response.Write("<ul>");
foreach (Memba.WebControls.ImageListItem objImageListItem
in ImageList2.ImageListItemCollection)
{
Response.Write("<li>" +
objImageListItem.Text + "</li>");
}
Response.Write("</ul>");
}
}
点击 F5 运行页面,然后点击提交按钮。响应应以项目符号列表显示两个图像列表的内容。观察到在回发时,图像列表保持其状态。
`ImageList` 控件在一个 HTML 隐藏字段中存储一个用 JSON 序列化的项目数组。
- 当您在页面加载时在服务器端添加项目时,这些项目只是被添加到隐藏字段中;
- 当页面在浏览器中渲染时,内置在控件中的 JavaScript 代码会读取隐藏字段中序列化的数组以渲染图像;
- 当使用控件的客户端 API 时,您只需向序列化到隐藏字段中的数组添加或删除项目;
- 当您回发页面时,隐藏字段会被回发,并且控件的服务器端代码允许您访问项目集合,该集合是从隐藏字段中读取的。
图像列表的内容也可以使用 JavaScript 代码在客户端更改。在页面 `</body>` 结束标签之前添加以下脚本
<script type="text/javascript">
<!--
// Declare global variables for the various controls
var g_ImageList1;
var g_ImageList2;
var g_txtItem;
var g_btnNew;
var g_btnCopy;
//pageLoad function of ASP.NET Ajax Extensions framework
function pageLoad()
{
//get a reference to the ImageList controls
g_ImageList1 = $find("<%= ImageList1.ClientID %>");
g_ImageList2 = $find("<%= ImageList2.ClientID %>");
//Add event handlers for the ImageList controls
if(g_ImageList1)
g_ImageList1.add_remove(onRemove);
//Get references to html controls
g_txtItem = $get("txtItem");
g_btnNew = $get("btnNew");
g_btnCopy = $get("btnCopy");
//Add event handlers for the click event of both html buttons
if(g_btnNew)
$addHandler(g_btnNew, "click", onBtnNew);
if(g_btnCopy)
$addHandler(g_btnCopy, "click", onBtnCopy);
}
//pageUnload function of ASP.NET Ajax Extensions framework
function pageUnload()
{
//Clear event handlers
if(g_ImageList1)
g_ImageList1.remove_remove(onRemove);
if(g_btnNew)
$clearHandlers(g_btnNew);
if(g_btnCopy)
$clearHandlers(g_btnCopy);
}
//Remove event handler for the ImageList controls
function onRemove(sender, args)
{
if((g_ImageList2) && (g_ImageList2.get_item(args.get_key())))
g_ImageList2.remove_item(args.get_key());
}
//click event handler for the btnNew button
function onBtnNew()
{
if(g_ImageList1 && g_txtItem)
{
//Instantiate a new item
var item = new Memba.WebControls.ImageListItem(
Memba.Utils.newGuid(),
'<%= this.ResolveClientUrl("~/images/angel.gif") %>',
g_txtItem.value
);
//Add the item to the list
g_ImageList1.add_item(item);
}
}
//click event handler for the btnCopy button
function onBtnCopy()
{
if(g_ImageList1 && g_ImageList2)
{
//Clone the array in ImageList1
var _arr = Array.clone(g_ImageList1.get_items());
for(var i = 0; i < _arr.length; i++)
{
//Copy any non-existing item to ImageList2
if(g_ImageList2.get_item(_arr[i].get_key()) == null)
g_ImageList2.add_item(_arr[i]);
}
}
}
//-->
</script>
ASP.NET AJAX 扩展提供了两个重要的 JavaScript 事件处理程序
pageLoad
由框架在页面 DOM 和脚本加载并初始化时调用。这是一个获取控件引用和添加事件处理程序的理想位置。pageUnload
由框架在页面卸载时调用。建议在此阶段清除处理程序。
该脚本为两个 HTML 按钮(`btnAdd` 和 `btnCopy`)的 `Click` 事件实现了事件处理程序。`btnAdd` 的 `Click` 事件处理程序向第一个图像列表添加一个新项目。`btnCopy` 的 `Click` 事件处理程序将 `ImageList1` 的内容复制到 `ImageList2`。
该脚本还为第一个图像列表的移除事件实现了一个事件处理程序。每次从第一个图像列表中移除项目时,如果该项目存在,它也会从第二个图像列表中移除。
按 F5 运行项目,然后单击各种按钮以体验 `ImageList`。
关注点
此图像列表是列表框的灵活且用户友好的替代方案,用于管理小型项目列表。对于更高级的开发人员,图像列表的源代码可在Codeplex、Google code 和Sourceforge.NET 上获取,并附有非常详细的注释。
历史
- 版本 1.0 - 日期:2007 年 12 月 18 日。