使用 JQuery 进行带持久化的拖放
如何创建拖放功能将用户添加到房间
引言
您是否曾经在网站上看到过拖放操作?它可能允许您将产品拖放到购物车中。我们大多数人都体验过,并且对这项功能印象深刻。在本文中,我们将重点介绍如何创建类似的拖放功能,将用户添加到房间。
为什么选择 JQuery?
为什么确实要选择 JQuery?市面上有许多免费的拖放库。例如,可以使用 Microsoft ASP.NET Ajax。不幸的是,Microsoft Ajax 库对开发者来说并不友好,也就是说,它非常复杂。所以,如果您正在寻找一些令人头疼的体验,请务必深入研究 Microsoft Ajax。但是,如果您对简单而强大的方法感兴趣,那么 JQuery
就是您的朋友。
有些人可能会想,“为什么不直接编写普通的 JavaScript 呢?” 当然可以,但这同样是一个非常复杂且耗时的过程。如果您只想使用 JavaScript,请参阅文章“浏览器兼容的拖放购物车”。
下载 JQuery 和 UI API
在实现任何功能之前,我们需要下载 JQuery
库和 JQuery
拖放 UI API。请查看以下链接进行下载:
场景
这个场景与购物车略有不同。在此应用程序中,我们将把用户拖放到一个房间。一旦用户被添加到房间,就会向数据库写入一条记录。我们也可以从房间中删除用户。在这种情况下,数据库中的记录也会被删除。请查看 GIF,链接为“使用 JQuery 实现带持久化的拖放”。
数据库
有一个名为 tblRoomSessions
的表,它将保存有关用户和房间的信息。下面显示了 tblRoomSessions
表的图示。

表脚本包含在下载文件中。
填充学生列表
有多种方法可以填充学生 DataList
控件。您可以使用简单的 DataSet
容器,将其填充来自 tblRoomSession
的数据,然后将其分配给 DataList
控件。我使用了不同的方法,但这实际上并不影响如何填充 DataList
。
学生 DataList 控件 ASPX 代码
DataList
控件的 ASPX 代码非常直接。请查看下面的代码:
<asp:DataList ID="dlRooms" EnableViewState="false" runat="server" RepeatColumns="3"
RepeatDirection="Horizontal">
<ItemTemplate>
<div id="div1" class="block">
<div style="text-align:center; font-size:18px; border:solid 1px">
<%# Container.ItemIndex + 1 %></div><li id="username" runat="server">
<%# Eval("UserName") %></li><li id="roomId" runat="server" style="visibility:hidden">
<%# Eval("RoomID") %></li><li>
<%# Eval("Subject") %></li><li>
<%# Eval("Description") %></li></div></ItemTemplate></asp:DataList>
当 DataList
被填充后,它看起来会像下面的截图:

数字表示学生请求房间的顺序。这意味着学号为 1
的学生比学号为 2
的学生先请求房间。这些数字是使用以下语句生成的:
<%# Container.ItemIndex + 1 %>
您还会注意到,ID 为 roomId
的 <LI>
被标记为 hidden
。您无需在每个 <LI>
中嵌入 roomId
,因为您在到达此页面之前就知道 roomId
。包含所有 <LI>
的 <DIV>
元素具有一个名为 block
的类。让我们在下一节中看看所有的样式。
CSS 样式
此应用程序使用了多种 CSS 样式。让我们看其中一些。
.block {
border: 2px solid #0090DF;
background-color: #68BFEF;
width: 200px;
height: 200px;
margin: 10px;
overflow:auto;
padding:1em 1em 1em 1em;
z-index:9999;
cursor:move;
}
block
样式用于所有可拖动的项。
.roomItem {
border: 2px solid #0090DF;
background-color: yellow;
}
roomItem
样式用于添加到房间的项。
.drop {
background-color: #e9b96e;
border: 3px double #c17d11;
width: 300px;
height: 300px;
margin: 10px;
overflow:auto;
position:absolute;
top: 5px;
right: 10%;
padding: 1em 0 0 0;
}
drop
样式用于放置区域 <DIV>
元素,在本例中是房间。
使用 JQuery 使项可拖放
我将首先发布完整的代码,然后分段解释代码。
$(document).ready(function(){
$(".block").draggable({helper:'clone'});
$(".drop").droppable({
accept: ".block",
activeClass: 'droppable-active',
hoverClass: 'droppable-hover',
drop: function(ev, ui) {
$(ui.draggable).addClass("roomItem");
var lid = ($(ui.draggable).children("li:first"));
// gets the username
var username = ($(ui.draggable).children("li:first").text()).replace(/[\n\r\t]/g,'');
var roomId = $(ui.draggable).children("li:eq(1)").text();
var removeLink = document.createElement("a");
removeLink.innerHTML = "remove";
removeLink.href = "#";
removeLink.onclick = function()
{
$("#drop1").children().remove("#"+lid[0].id);
$(this).remove();
// removes the class
$(ui.draggable).removeClass("roomItem");
// adds the new class
$(ui.draggable).addClass("block");
// remove the user session from the database
VirtualTutoringRoomWebApps.VirtualRoomService.removeUserFromRoom(
username,Number(roomId));
}
$(this).append($(ui.draggable).clone().children("li:first").addClass("roomItem"));
$(this).append(removeLink);
// add user to the room
VirtualTutoringRoomWebApps.VirtualRoomService.addUserToRoom(username,Number(roomId));
}
});
});
看起来很复杂!别担心;并不难理解。让我们从 document.ready
函数开始,该函数在 DOM(文档对象模型)准备好并加载后触发。
要使元素可拖动,您只需要使用 JQuery
UI API 提供的 draggable 函数。该函数可以接受不同的参数,但我们使用了类的名称,在本例中是 .block
。这意味着“使所有类为 .block
的元素可拖动”。draggable 函数还接受 helper。Helper 用于对可拖动项执行操作。我们正在使用 clone
helper,它将为我们的可拖动项创建一个 clone
。
$(".block").draggable({helper:'clone'});
创建放置区域也使用了相同的技术。当项被放到放置区域内时,一个名为 roomItem
的类会被添加到该项。这会给该项应用黄色背景,表明该项已被放入放置区域。然后,我们使用以下代码从可拖动的 <DIV>
元素内的 <LI>
项中提取 username
和 roomId
。
// gets the username
var username = ($(ui.draggable).children("li:first").text()).replace(/[\n\r\t]/g,'');
var roomId = $(ui.draggable).children("li:eq(1)").text();
创建了一个新的超链接元素,用于从放置区域中删除项。基本上,remove
链接用于将用户从房间中移除。
var removeLink = document.createElement("a");
removeLink.innerHTML = "remove";
removeLink.href = "#";
removeLink.onclick = function()
{
$("#drop1").children().remove("#"+lid[0].id);
$(this).remove();
// removes the class
$(ui.draggable).removeClass("roomItem");
// adds the new class
$(ui.draggable).addClass("block");
// remove the user session from the database
VirtualTutoringRoomWebApps.VirtualRoomService.removeUserFromRoom(
username,Number(roomId));
}
当项从放置区域移除时,它会返回到其原始类,即 block
。服务器端 removeUserFromRoom
方法被触发,该方法将项从数据库中移除。我们将在本文稍后介绍此方法。当我们拖放项到放置区域时,我们将第一个 <LI>
元素附加到放置区域。在本例中,这是用户的 username
。
$(this).append($(ui.draggable).clone().children("li:first").addClass("roomItem"));
$(this).append(removeLink);
// add user to the room
VirtualTutoringRoomWebApps.VirtualRoomService.addUserToRoom(username,Number(roomId));
请查看下面的截图,显示了添加到放置区域的项。

最后,addUserToRoom
方法被触发,并将用户添加到房间。
Ajax 方法
我使用了 Microsoft ASP.NET Ajax 来创建到 Web 服务方法的异步调用。让我们看看这些方法:
[WebMethod]
public bool removeUserFromRoom(string username, int roomId)
{
MethodInvoker.Invoke<SQLDataAccess>("RemoveUserFromRoom", new object[]
{
username.Trim(), roomId
});
return false;
}
[WebMethod]
public bool addUserToRoom(string username, int roomId)
{
try
{
MethodInvoker.Invoke<SQLDataAccess>(
typeof(tblRoomSession), "AddAndPersistAll",
new object[]
{
new tblRoomSession()
{
Guid = Guid.NewGuid().ToString(), RoomID = roomId,
StudentUserName = username.Trim(),
TutorUserName = User.Identity.Name, IsSessionStarted = true,
SessionStartDate = DateTime.Now
}
});
}
catch (Exception ex)
{
string exception = ex.Message;
}
return false;
}
不要太在意 MethodInvoker
类。这是一个自定义类,用于在对象上创建数据访问操作。您可以使用 DataSet
、Entity
类、Manager
、Repository
和 Mapper
来执行数据访问操作。如果您对 MethodInvoker
类感兴趣,请参阅博文“MethodInvoker”。
附加功能
此应用程序还需要实现一些额外的功能。其中一些列在下面:
- 一个计时器,它将异步获取等待房间的用户,而无需刷新页面。
- 不允许将重复用户添加到同一个房间。
更新
在发布时,我们讨论了一些可能有用的附加功能。其中一些显示在上面的“附加功能”部分。这里实现了这两个功能。
首先,让我们看看当新用户进入等待列表时如何更新界面。这个过程应该是异步的,这意味着屏幕不应在服务器端刷新,而应在客户端刷新。事实证明,这可以通过使用 ASP.NET Timer
控件轻松完成。Timer 控件将触发一个事件,该事件将触发服务器端的一个方法。首先,您需要在 UpdatePanel
控件内添加 Triggers 部分。
<triggers>
<asyncpostbacktrigger eventname="Tick" controlid="timer1">
</triggers>
现在,让我们看看同样包含在 UpdatePanel
控件内的 Timer 控件。
<timer id="timer1" ontick="timer1_Tick" interval="5000" runat="server" />
Timer
控件每 5 秒触发一次 timer1_Tick
事件。现在,让我们看看 timer1_Tick
事件:
protected void timer1_Tick(object sender, EventArgs e)
{
BindData();
up1.Update(); }
这很简单!timer1_Tick
事件通过 BindData
方法从数据库获取数据,然后刷新 UpdatePanel
以更新用户界面。一切运行良好……持续 5 秒。5 秒后,您将无法拖放您的对象。
原因在于,当您使用 UpdatePanel
更新屏幕时,它会重置其中的所有控件。现在,您可以看到控件,但它们没有任何功能。有一个简单的方法可以解决这个问题。您所要做的就是再次使元素可拖动。请查看下面的实现:
protected void timer1_Tick(object sender, EventArgs e)
{
BindData();
up1.Update();
RegisterDragAndDropScript();
}
// this method is fired to register the scripts again
// since the timer will refresh the contents of the
// update panel and hence the HTML controls will lose
// the drag and drop capability
private void RegisterDragAndDropScript()
{
string script = "makeElementsDraggableAndDroppable();";
ScriptManager.RegisterClientScriptBlock(this,this.GetType(),
"DragAndDropScript", script, true);
}
现在,当 UpdatePanel
刷新时,控件再次变得可拖动。
结论
在本文中,我们学习了如何使用 JQuery
和 JQuery
UI API 创建拖放 UI。希望您喜欢这篇文章;祝您编码愉快!
历史
- 2008 年 3 月 5 日 -- 最初版本发布
- 2008 年 3 月 7 日 -- 文章更新