Implementing Draggable User controls in ASP.NET
Posted On April 5, 2007 by Ramdas S filed under Internet
We will be using LGPL JavaScript drag and drop library from http://www.walterzorn.com to avoid the reinventing wheel. This is a fine library that offers more than just drag and drop, and works with multiple browsers. So, first make sure you download wz_dragdrop.js from this site, which includes great demonstrations of library in action.
User controls examples
User controls are reusable web components. They can be contained in a WebForm, typically a *.aspx page. I have made three very simple ASP.NET user controls:
1. PersonalInfo.ascx - a user control to capture First and Last Name;
2. AddInfo.ascx - to capture address details; and
3. ContactInfo.ascx - captures phone numbers and email IDs.
Check out figure 1 to see how they look!
![]()
Fig. 1
The ASP.NET page Demo.aspx hosts the user controls and has a ‘Submit’ button. Right now, the controls don’t do much. They have a public method ConvertToUpper that converts text to upper case.
Drag and Drop JavaScript
The script ‘wz_dragdrop.js’ is really simple to use. To use it, all we need to do is add the following line just after the tag in demo.aspx:
<script type="text/javascript" src="wz_dragdrop.js">
Make sure that you extract the script from the downloaded archive to the location mentioned in the ‘src’ attribute. At this point, you may want to open the script file, have a look at the license and the code inside it.
Making the controls draggableThis part is very simple. Here, the script carries out most of the work. User controls are included in a WebForm using the <%@ Register …%> tag as shown in code 1.
Code 1
<%@ Register TagPrefix="UC1" TagName="PersonalInfo" Src="PersonalInfo.ascx" %>
<%@ Register TagPrefix="UC2" TagName="ContactInfo" Src="ContactInfo.ascx" %>
<%@ Register TagPrefix="UC3" TagName="AddInfo" Src="AddInfo.ascx" %>
<html>
<head>
</head>
<body>
<script type="text/javascript" src="wz_dragdrop.js"></script>
<form runat="server">
<UC1:PERSONALINFO id="ucPersonalInfo" runat="server"> </UC1:PERSONALINFO>
<UC2:CONTACTINFO id="ucContactInfo" runat="server"></UC2:CONTACTINFO>
<UC3:ADDINFO id="ucAddInfo" runat="server"></UC3:ADDINFO>
…
</form>
</body>
</html>
First, we need to enclose all the user controls inside a <div> tag with a unique ID. Then, just before </body> tag, we call a function from the drag and drop script file and pass ID’s of all the <div> tags as parameters. Refer code 2.
Code 2
<body>
…
…
<div id="personalinfo" style="LEFT: 10px; POSITION: absolute; TOP: 10px">
<UC1:PERSONALINFO id="ucPersonalInfo" runat="server"></UC1:PERSONALINFO>
</div>
<div id="contactInfo" style="LEFT: 10px; POSITION: absolute; TOP: 90px">
<UC2:CONTACTINFO id="ucContactInfo" runat="server"></UC2:CONTACTINFO>
</div>
<div id="addinfo" style="LEFT: 10px; POSITION: absolute; TOP: 190px">
<UC3:ADDINFO id="ucAddInfo" runat="server"></UC3:ADDINFO>
</div>
…
…
<script language="javascript">
SET_DHTML("personalinfo","contactInfo","addinfo");
</script>
</body>
Note that we have specified absolute positioning for the grids. For drag and drop to work, this is a must. Also, notice the call to ‘SET_DHTML’, it can accept any number of parameters.
That’s it! If you access this page from IIS (http://localhost/Demo.aspx), you should be able to drag and drop the user controls. Also note that the validations are fired whenever you enter invalid values. Our primary objective has been achieved!
Maintaining the position across postback
However, we still have not tackled one problem. If you have a button or any other control on the screen that causes postback, you will see that the controls will not retain their positions across postback. There are many ways of getting over this. Here, we will see a very simple mechanism of retaining the positions of controls on clicking buttons using JavaScript and hidden HTML fields.
I have written two JavaScript functions for this. The first one, SetDivPos, accepts an ID of <div> and input field. The input text field contains comma separated left and top positions of the <div> tag. We will have three hidden input fields, one for each user control. The second function ‘GetDivPos’ does exactly the opposite. It saves the left and top positions of a <div> tag to an input field. See code 3.
Code 3
function SetDivPos(divID,inputID){
try{
var div = document.getElementById(divID);
var input = document.getElementById(inputID);
var arrXYPos = input.value.split(',');
if (arrXYPos.length <2) return;
div.style.top=arrXYPos[1];
div.style.left=arrXYPos[0];}
catch (e)
{alert("Following error occurred in Drag & Drop Script:" +e.value);}
}
function GetDivPos(divID,inputID){
try{
var div = document.getElementById(divID);
var input = document.getElementById(inputID);
input.value= div.style.left +","+div.style.top;}
catch (e)
{alert("Following error occurred in Drag & Drop Script:" +e.value);}
}
SetDivPos is called three times, every time the page loads by placing it before </body> tag and after call to SET_DHTML. Check out code 4.
Code 4
<script language="javascript">
SET_DHTML("personalinfo","contactInfo","addinfo");
SetDivPos('personalinfo','hidPersonalInfo');
SetDivPos('contactInfo','hidContactInfo');
SetDivPos('addinfo','hidAddInfo');
</script>
Here, we have a single button that may cause postback. So, we hook it to its client side onclick handler using ASP.NET server side code. This is an important step. Since the button is server side control, we should always attach client side JavaScript handlers using server side code. In the server side code for Demo.aspx we write the following lines (code 5).
Code 5
void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{ucAddInfo.ConvertToUpper();
ucPersonalInfo.ConvertToUpper();
}
btn1.Attributes.Add("onclick","SaveXYPos();");
}
The complete code for the article has been included on one of the accompanying CDs (source code section). Open the readme.txt file in Drag_Drop.zip on the CD for instructions on running the demo. Now, try running the page using the URL. You should be able to enter text into fields and drag the controls around. Now, if you have not noticed, I have added some validators to the text fields. If you click submit, postback occurs, text in the fields gets converted to upper case and user controls maintain their position! Refer figures 2 and 3.
![]()
Before clicking Submit![]()
After clicking Submit
Doing more
A nice way to avoid the problem of retaining positions would be to use AJAX. We will discuss that some other day. You may also like to have controls dragged from one bounding rectangle to another, instead of placing them anywhere on the screen. This will ensure that they will not overlap. This will again require some more of javascripting.
This article illustrated how exciting features could be added to ASP.NET user controls without much effort. The best part of the method discussed here is that it can be incorporated very easily in existing ASP.NET applications.
Please share your comments and criticism with me at: ashish_patil0@yahoo.com.
