Click here to Skip to main content
Email Password   helpLost your password?

Screenshot.jpg

Introduction

This tutorial is intended to explain quickly how to implement drag and drop using the ASP.NET 2.0 AJAX Futures November CTP. To explain this technology, I've created a simple project with a custom AJAX control that implements a jigsaw puzzle game.

Background

When I started to learn the new ASP.NET AJAX framework, I asked my company to buy a book, and I chose an amazing book:

In this book, I found a chapter that explains how to use the PreviewDragDrop to implement drag and drop on web. I used this chapter and other information from Internet (Google) to create my AJAX control.

The ASP.NET AJAX Framework

The basic idea within the ASP.NET AJAX Framework is to have a possibility to use object-oriented programming in JavaScript (simulated OOP) and make it similar to C#. Most C# features are available in JavaScript: namespace, class, interface, enum etc. Besides the OOP features is available the possibility to implement visual custom controls (client side controls) that extend the HTML elements' functionalities.

Basically, we have two types of controls (visual controls):

The difference is just logic, but whilst generally Sys.UI.Behavior is used to extend HTML element behaviors for different types of elements, Sys.UI.Control is used to extend HTML element behaviors for a single type of element.

For example, if we want to implement a behavior that shows an alert on the click event, we can create a class that extends Sys.UI.Behavior, and then we can use this code with several HTML element types: DIV, SPAN, INPUT etc.

//Namespace declaration
Type.registerNamespace("MyNamespace");

//Constructor
MyNamespace.MyBehavior = function(element)
{
   MyNamespace.MyBehavior.initializeBase(this, [element]);
}

MyNamespace.MyBehavior.prototype =
{
   initialize : function()
   {
     // Add event handler on click
      // Parameters: 
      // 1) The HTML element
      // 2) Event name without "on" ("onclick"="click")
      // 3) Control instance
      $addHandlers(this.get_element(), { "click" : this._onClick }, this);
   },

   dispose : function()
   {
      // Remove all events handlers for the current HTML element
      $clearHandlers(this.get_element());
   },

   // Event handler onclick
   _onClick : function(evt)
   {
      // Show the id of current HTML Element
      alert(this.get_id());
   }
};

// Register class
MyNamespace.MyBehavior.registerClass("MyNamespace.MyBehavior", Sys.UI.Behavior);

When we need to use it within our page, we can just write the following code:

// Create an instance of our Behavior
// and attach it to HTML element with id 'elementId'
// Parameters:
// 1) Class name with namespace
// 2) Properties in JSON format
// 3) Events in JSON format
// 4) References in JSON format
// 5) HMTL element
$create(MyNamespace.MyBehavior, {}, {}, {}, $get('elementId'));

If we need to implement behaviors for an element type or we need to implement a complex control (a visual control composed of different elements), we need to extend Sys.UI.Control.

AJAX Enabled Server Control

Generally, control are not manually created using $create in JavaScript, but automatically generated by an ASP.NET Server Control (server side version of the control). This way, we can implement a server control and have design-time support within Visual Studio. When we want to create a AJAX enabled Server Control, we need to extend ScriptControl (instead of WebControl). This base class contains all methods useful to make a relation between the client control (JavaScript) and the server control (.NET).

In ScriptControl, we need to override two methods:

protected override IEnumerable<System.Web.UI.ScriptDescriptor> GetScriptDescriptors()
{
    if (!string.IsNullOrEmpty(this.Filename))
    {
        ScriptControlDescriptor descriptor = new 
          ScriptControlDescriptor("JigsawPuzzleGameControl.PuzzleGameAjax", 
          this.ClientID);
        descriptor.AddProperty("nRows", this.NRows);
        descriptor.AddProperty("nColumns", this.NColumns);

        yield return descriptor;
    }
}
         
protected override IEnumerable<System.Web.UI.ScriptReference> GetScriptReferences()
{
    if (!string.IsNullOrEmpty(this.Filename))
    {
        List<ScriptReference> scripts = new List<ScriptReference>();

        ScriptReference scriptReference1 = new ScriptReference("PreviewScript.js", 
                                           "Microsoft.Web.Preview");
        scripts.Add(scriptReference1);

        ScriptReference scriptReference2 = new ScriptReference("PreviewDragDrop.js", 
                                           "Microsoft.Web.Preview");
        scripts.Add(scriptReference2);

        ScriptReference scriptReference3 = new ScriptReference();
        scriptReference3.Path = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), 
                                "JigsawPuzzleGameControl.Resources.Helpers.js");
        scripts.Add(scriptReference3);

        ScriptReference scriptReference4 = new ScriptReference();
        scriptReference4.Path = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), 
                                "JigsawPuzzleGameControl.Resources.PuzzleGameAjax.js");
        scripts.Add(scriptReference4);

        return scripts;
    }
    else
    {
        return new List<ScriptReference>();
    }
}

Drag and Drop

To implement drag and drop in our control, we need to implement two interfaces within two client controls:

In Sys.Preview.UI.IDropTarget, we need to implements the following methods:

We also need to add an event handler within the method Initialize for the MouseDown event and then call Sys.Preview.UI.DragDropManager.startDragDrop:

initialize : function()
{
    JigsawPuzzleGameControl.DragPuzzleGameAjaxElement.callBaseMethod(this, 
                                                            "initialize");
    $addHandlers(this.get_element(), 
      { "mousedown" : this._onMouseDown }, this);
},

_onMouseDown : function(evt)
{
    window._event = evt;
    evt.preventDefault();
    
    Sys.Preview.UI.DragDropManager.startDragDrop(this, 
                            this.get_element(), null);
},

In Sys.Preview.UI.IDragSource, we need to implement the following methods:

We also need to register and unregister the client component as the drop area:

initialize : function()
{
    JigsawPuzzleGameControl.DropPuzzleGameAjaxElement.callBaseMethod(this, "initialize");
    Sys.Preview.UI.DragDropManager.registerDropTarget(this);
},

dispose : function()
{
    Sys.Preview.UI.DragDropManager.unregisterDropTarget(this);
    JigsawPuzzleGameControl.DropPuzzleGameAjaxElement.callBaseMethod(this, "dispose");
},

The Game

The project is divided into two projects:

  1. A web site containing an example of using the control
  2. A library project containing the control

Within the library project is a class called PuzzleGameAjax that extends ScriptControl (the base class for all custom controls in AJAX). This class is the server side code of my control.

On the client side, we have three JavaScript classes:

DropPuzzleGameAjaxElement implements the Sys.Preview.UI.IDropTarget interface and DragPuzzleGameAjaxElement implements the Sys.Preview.UI.IDragSource interface. These two interfaces are used by the AJAX framework to handle the drag and drop in a generic way.

Points of Interest

AJAX ASP.NET is a very good technology, and I'm currently working with it to implement a very complex behavior to improve the user experience. The drag and drop feature is absolutely the most user friendly feature, and it makes a software very intuitive to use. Normally, on web, this feature takes a lot of JavaScript code, but with PreviewDragDrop, everything is easy.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralThis is Excellent! Thanks for posting this.
stever(398)
16:19 17 Mar '10  
Hi,

Just wanted to say thanks for posting this. Super cool.
QuestionHow to use it on a website?
imgr883
18:37 9 Sep '09  
I was just searching for Jigsaw puzzle codes and yours was the only one I found that actually made some sense to me and looked like the real deal at the same time, and ofcourse it was free as well Big Grin I downloaded both the sample and the source code for VS2008 and I tried testing it on localhost and on the web server as well but the browser showed me the source code instead. I uploaded the folder that is in the 'sample' zip file. I dont know what the problem is. I saved the demo page that you shared and it works fine. Can you please explain what I am doing wrong? Also, how can I make the the input image for the puzzle a permanent link that I can control? Any help would be great and thanks for the awesome code, you seem to be the only one on the whole world wide web with the code Smile
AnswerRe: How to use it on a website?
Ferreri Gabriele (Megasoft78)
21:27 9 Sep '09  
Hi,
I'm actually using Visual Studio 2005 on my machine. It should be the same I think.
Extract the JigsawPuzzleGame.zip (sample) in a folder and from Visual Studio 2005, menu File / Open Web Site. Select the folder you just extract.
Right click on Puzzle.aspx and select menu "Set As Start Page". Now run the web application and should work Smile
If you like to have a specific image automatically selected you have to write the following code:

   this.PuzzleGameAjax.MaxWidth = 400;
this.PuzzleGameAjax.MaxHeight = 300;
this.PuzzleGameAjax.NRows = 5;
this.PuzzleGameAjax.NColumns = 5;
this.PuzzleGameAjax.StartGame(File.ReadAllBytes(@"C:\MyPhoto.jpg"));

MaxWidth and MaxHeight are used to resize automatically your photo mantaining the aspect ratio. NRows and NColumns are used to split the photo in multiple pieces. StartGame method is used to start creating the puzzle using that photo.
I hope this help you. If not please let me know.

Cheers,
Gabriele

Your mind is like a parachute. It works best when open.

GeneralRe: How to use it on a website?
imgr883
13:36 10 Sep '09  
Thank you so much, this worked perfect!! I can't thank you enough Big Grin
Generalhow to use a unique image
yasi22
9:26 11 Aug '09  
hi
this page is great
but my problem is that i want to
specify a picture and use this as puzzle background picture
.i dont want to let the user select the picture
what should i do
thanks
GeneralRe: how to use a unique image
Ferreri Gabriele (Megasoft78)
21:10 11 Aug '09  
Hi,
I think you need just to remove the handler mousedown in initialize javascript method, but in this case you don't need the drag and drop functionality at all.
Gabriele.

Your mind is like a parachute. It works best when open.

Generalthis.get_enableControl()
Patch79
23:55 13 Nov '08  
What does this line in puzzlegame.js do?
I cannot find where it is defined - please can you explain?
Many thanks
Phil
GeneralRe: this.get_enableControl()
Ferreri Gabriele (Megasoft78)
2:10 14 Nov '08  
Hi Phil,
The this.get_enableControl() method is the get of "enableControl" property.
This property is generate dynamically from the constructor with the following line:
JigsawPuzzleGameControl.PuzzleGameAjax.createProperty("enableControl");

Check in Helpers.js I used some code from the fantastic book "Ajax in Action".

Gabriele.

Your mind is like a parachute. It works best when open.

Generalnot working
sp4ceman
22:27 28 Aug '08  
the code compiles and runs, i load up a picture (its small about 400*300px) and it generates the picture on the left and then it seems to put all the "pieces" on top of one another on the right.

i try drag from the right and nothing happens.
in debug mode no events fire. it just sits there.

i have tried in ie7 and firefox, but i just cant get the thing to drag....
GeneralRe: not working
Ferreri Gabriele (Megasoft78)
4:09 30 Aug '08  
Hi,
I'm sorry but I test it on IE6 and work fine. In firefox and IE7 I have a bug to fix. In debug mode no events fire because you can't you breakpoints but you have to use debugger keyword in your javascript code. I'll try to fix this bug as soon as I can.

Cheers,
Gabriele.

Your mind is like a parachute. It works best when open.

GeneralRe: not working
srkanna
1:13 2 Sep '08  
fdsaf
GeneralonDrag:
masko
18:02 29 Jun '08  
Thanks for the great sample. Just a bit off topic question. Is it possible to restrict an elements movement only in the horizontal or vertical direction? I have been trying to do this in the onDrag: function()? Is this the right place to do this as my code below does not work properly (only moves in the vertical direction Confused though u'd expect it to move only in the horizontal) ?

onDrag: function()
{
if (this._visual) {
this._visual.style.top = "50px";
}
},

(where this.visual is the moving element)
Thanks
AnswerRe: onDrag:
Ferreri Gabriele (Megasoft78)
3:02 30 Jun '08  
Hi,
I'm not sure it's possible! I already had the same problem in my custom Grid for resize columns and I used a custom code to implement this behaviour. In theory it should work but the problem is that in javascript is not easy to define somethink that really work always! Smile
Why do you need to make fix the movement during your drag and drop?

Cheers,
Gabriele.

Your mind is like a parachute. It works best when open.

GeneralRe: onDrag:
masko
12:33 30 Jun '08  
Thanks for the quick reply.
I am trying to build something similar to http://zendold.lojcomm.com.br/icarousel/example3.asp[^] with the addition that a user can drag one of the images and then it would scroll in the direction of the drag. I am using some scripts featured on dynamic drive for the drag functionality http://www.dynamicdrive.com/dynamicindex11/domdrag/index.htm[^]
I have got it working in custom script but came across a problem in VS 2008 where I had the menu container div inside an update panel, so when ever a partial refresh occurred i kept getting "anonymous code" files in the vs debugger and they kept growing..

so i thought of doin the script using the ms ajax framework..
(The "anonymous code" problem goes away when i take the container div out of the update panel.. so thats kinda my fix at the moment)
GeneralRe: onDrag:
Ferreri Gabriele (Megasoft78)
10:59 1 Jul '08  
Hi,
I'm sorry but without a sample of your code I can't help you!Frown
If you like you can send to me an email with a sample project in Visual Studio 2008 and I can try to understand where is the problem. My email address is megasoft78@yahoo.it

Cheer,
Gabriele.
GeneralGood one
Alexey.Kucherenko
21:41 21 Apr '08  
Gratz, nice article. Could you provide online demo?
GeneralRe: Good one
Ferreri Gabriele (Megasoft78)
12:59 22 Apr '08  
Hi,
I found a free host and I provide a demo online. I've tested only on Vista with IE7.

Cheers,
Gabriele

Your mind is like a parachute. It works best when open.

GeneralRe: Good one
Alexey.Kucherenko
21:41 22 Apr '08  
Thanks a lot for demo.
Really nice, tested with FF 2.0 and XP.
I will test it local in some days in other browsers too
GeneralLooks Great
Preston Noe
12:10 16 Apr '08  
This is a really great example of using Drag and Drop. I did notice one thing though. I tried to debug the control, and in order to do so, I had to set debug="true" in the web.config. When I do this and run my website with the puzzle control on it, dragging a piece of the puzzle around the page causes IE to freeze and I get a message about a Javascript running that is causing Internet Explorer to slow down. At this point, I have to kill the browser. When I set debug="false" in the web.config, everything runs fine. I was wondering if you had run into this yourself and if so, if you were able to determine a definitive reason for it.
GeneralRe: Looks Great
Ferreri Gabriele (Megasoft78)
9:59 17 Apr '08  
Hi,
I've tried with Visual Studio 2005, Vista, Internet Explorer 7 and work fine.
What is your configuration?
What do you means when you say "I tried to debug the control" during drag and drop?
Have you put a "debugger" statement into javascript method?

Cheers,

Gabriele.

Your mind is like a parachute. It works best when open.

GeneralRe: Looks Great
Preston Noe
4:21 18 Apr '08  
My setup is VS 2008 and win xp. I built your project, and added a new default.aspx page. I added a ScriptManager and instance of the Puzzle Game Control and set the filename to the name of a photo on my machine. I tried to start with debugging, and I was asked to change the web.config to enable debugging. In the web.config, there is a debug="false" statement. I set this to true. I restart the site with debugging. I am using IE 7 and at this point the drag controls are moving slower, but as you continue to move them around the page, at some point I get a popup message about a script causing IE to run slow. If I set the debug="false" again in the web.config and restart, it works great. Its a weird behavior that could probably be explained by the overhead that IE is doing with the Javascript debugging, but I thought I would get your opinion on the matter.
GeneralRe: Looks Great
Ferreri Gabriele (Megasoft78)
10:55 18 Apr '08  
Hi,
I tried to follow your steps and if I set the image on load event my control not show correctly the images. The problem is within the time necessary to split the image into several images. The debug statement in web.config have impact only on c# code because the compiler jump to write pdb files (debug info) and the server code run faster. If you want have better performance with Ajax Framework you need to change in ScriptManager the property ScriptMode from Auto to Release. This load release version (the same without parameters check) of Ajax Framework into the browser. My browser (IE7 on Vista) is not crash during my test but if you want that control work correctly you need to call StartGame method on different event (click on button). If you want, just send me by e-mail your code and I'll try to understand the problem.

Cheers,
Gabriele Wink

Your mind is like a parachute. It works best when open.

GeneralStill doesn't work for me
web developer
17:33 8 Apr '08  
Hi Ferreri,
Could you please explain to me step by step on how to set up this project and get running. ie how do I load up the gamecontrol project as well.
currently it doesn't compile instead it comes up with an error saying "The debugger cannot continue running the process. The project file '' has been renamed or is no longer in the solution."

Am using Visual Web Developer 2008 if that will help you at all.

Thanks.
GeneralRe: Still doesn't work for me
Ferreri Gabriele (Megasoft78)
12:15 9 Apr '08  
Hi,
Probably it doesn't work because Visual Studio 2008 Express Edition doesn't support multiple projects.
I've splitted the solution in 2 separated projects and I've created a specific version for Visual Studio 2008.
Now you download the example for Visual Studio 2008 and run it.
To open a web site from Visual Studio 2008 you must extract the zip file and from Visual Studio menu File / Open Web Site and select the folder extracted.
At this point you just run it.
I hope this helps you.
If you have other problems ask again. Smile

Cheers.

PS: You must have installed ASP.NET Ajax Extension
http://www.microsoft.com/downloads/details.aspx?FamilyID=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&displaylang=en[^]

Your mind is like a parachute. It works best when open.

GeneralRe: Still doesn't work for me
web developer
14:36 9 Apr '08  
Thanks Ferreri,
That worked just fine, awesome code!


Last Updated 20 Apr 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010