Fetstil Fetstil Kursiv Understrykning linje färgläggning tabellverk Punktlista Nummerlista Vänster Centrerat högerställt Utfyllt Länk Bild htmlmode
  • Forum & Blog
    • Forum - översikt
      • .Net
        • asp.net generellt
        • c#
        • vb.net
        • f#
        • silverlight
        • microsoft surface
        • visual studio .net
      • databaser
        • sql-server
        • databaser
        • access
        • mysql
      • mjukvara klient
        • datorer och komponenter
        • nätverk, lan/wan
        • operativsystem
        • programvaror
        • säkerhet, inställningar
        • windows server
        • allmänt
        • crystal reports
        • exchange/outlook
        • microsoft office
      • mjukvara server
        • active directory
        • biztalk
        • exchange
        • linux
        • sharepoint
        • webbservers
        • sql server
      • appar (win/mobil)
      • programspråk
        • c++
        • delphi
        • java
        • quick basic
        • visual basic
      • scripting
        • asp 3.0
        • flash actionscript
        • html css
        • javascript
        • php
        • regular expresssion
        • xml
      • spel och grafik
        • DirectX
        • Spel och grafik
      • ledning
        • Arkitektur
        • Systemutveckling
        • krav och test
        • projektledning
        • ledningsfrågor
      • vb-sektioner
        • activeX
        • windows api
        • elektronik
        • internet
        • komponenter
        • nätverk
        • operativsystem
      • övriga forum
        • arbete karriär
        • erbjuda uppdrag och tjänster
        • juridiska frågor
        • köp och sälj
        • matematik och fysik
        • intern information
        • skrivklåda
        • webb-operatörer
    • Posta inlägg i forumet
    • Chatta med andra
  • Konto
    • Medlemssida
    • Byta lösenord
    • Bli bonsumedlem
    • iMail
  • Material
    • Tips & tricks
    • Artiklar
    • Programarkiv
  • JOBB
  • Student
    • Studentlicenser
  • KONTAKT
    • Om pellesoft
    • Grundare
    • Kontakta oss
    • Annonsering
    • Partners
    • Felanmälan
  • Logga in

Hem / Artiklar / Titel på artikeln

Implementera drag’n drop med en ASP.NET kontroll, del 1

Postad 2004-07-16 av Mikael Deurell i sektionen ASP.NET, C#, Okategoriserat med 0 Kommentarer | Läst av: 8527, Betyg: 98%

Förord

Jag brukar svepa igenom forumen här på Pellesoft för att få inspiration till nya programmeringsutmaningar. För några dagar sedan dök det upp en fråga om hur man skulle kunna komma åt drag’n drop händelser i ASP.NET. Till min förvåning blev de flesta svaren lika korta som koncisa; ASP.NET är en serverteknologi och du bör använda JavaScript, Flash eller annan klientteknologi. En liten känsla jag fick var att vår frågeställare var mer skolad än så och var väl medveten om att ASP.NET är en serverteknologi. Jag tror att han undrade om man inte kunde använda ASP.NET som bas för att leverera en komplett komponentbaserad drag’n drop lösning. Klart att man kan...
Innehåll
  » Inledning
  » Let the fun begin, enter behaviors
  » Hello World
  » Man är inte smartare än den man kopierar
  » Drag’n drop komponenten
  » Interface och initiering
  » Koppla komponenten till elementet
  » Slutord
  » Nästa artikel, ASP.NET kontrollen


Inledning

Hursomhelst, jag tyckte detta lät hur kul som helst och lösningen blev att skriva en generell ASP.NET kontroll som automatiskt kapslar HTML element inom kontrollen och gör att denna kan draggas och droppas och generera events på serversidan till de som är intresserade. Det enda som skall behöva göras av utvecklaren är att han/hon drar in en drag’n drop kontroll på en ASP.NET sida och lägger in HTML element som underelement i denna. Sedan skall allt skötas automatiskt. Hur svårt kan det vara?

Exempel:


En massa HTML



Med bakgrund av de smällar jag åkt på tidigare i projekt där man använt en större mängd JavaScript på klienten, och med min (trots .net) oförändrat stora kärlek till COM, bestämde jag mig för att kapsla in drag’n drop logiken på klienten i en generell DHTML behavior komponent som jag kan koppla till de aktuella HTML elementen.

Detta medför båda för- och nackdelar, fördelarna är att vi får en ren design med en COM baserad DHTML behavior komponent (förpackad i en .htc fil) och vi slipper skräpa ner HTML koden med en massa JavaScript. Nackdelen är att behaviors bara fungerar i Internet Explorer, detta kan jag personligen leva med då jag tänker använda denna kontroll i mitt CMS system där administrationsgränssnittet ändå måste köras i Internet Explorer.

Jag har delat upp denna artikel i två delartiklar där den första behandlar klientdelen. Fokus i denna del läggs på design och programmering av den DHTML behavior komponent som kommer att bidra med generell drag’n drop funktionalitet till HTML element . Serverdelen består av skapandet av den av System.Web.UI.WebControls.WebControl ärvda komponent som kommer att använda klientlogiken från HTC komponenten och snappar upp de events som denna genererar.

Målet med allt detta är enkelt, efter den andra artikeln så ska vi ha en fungerande generell drag’n drop komponent som kan infogas i Visual Studio.NETs toolbox och användas som vilken annan kontroll som helst!


Let the fun begin, enter behaviors

För er som inte tidigare bekantat er med MSIE behaviors kommer här en liten introduktion.
Min erfarenhet av klientprogrammering i browsermiljö är klart färgad. Över hälften av de applikationer som jag varit i kontakt med som innehåller större mängder JavaScript har en design som kan skrämma den mest härdade av utvecklare. Microsoft måste ha haft ungefär samma erfarenheter när de för några år sedan tog fram behaviors till Internet Explorer, en teknologi färgad av COM då detta var innan .NET eran. DHTML Behaviors implementeras i grunden som COM komponenter (våra gamla kära IUnknown implementatörer) som kan kopplas till HTML element via dess style attribut. Detta gör att webbläsare som inte stödjer behaviors (läs alla utom MSIE) helt enkelt bara ignorerar detta attribut. Det går att skriva behaviors i C++, VB Script eller JavaScript. För enkelhetens skull kommer jag att skriva logiken i JavaScript.


Hello World

Vad vore en introduktion utan ett ”hello world” exempel? Grunden till alla HTC komponenter består av följande struktur;







Koden ovan skapar en enkel HTC (HTML Control). Den är tämligen ointressant som den ser ut nu så vi kompletterar denna med lite logik. Det givna HelloWorld exemplet för behaviors är givetvis implementation av rollover (när man drar musen över ett element så byter det färg). Här kommer en sådan komponent;

rollover.htc










Detta är den kompletta rollover komponenten. Vi kopplar komponentens Init() metod till window.onload så att vi initierar komponenten med rätt rollover färg (plockas från HTML elementets rollOverColor attribut om det finns, annars röd). Vi har deklarerat en PUBLIC:PROPERTY rollOverColor vilket binds till detta attribut på det aktuella HTML elementet. På detta sätt kan vi läsa egna attribut från HTML elementet och använda dessa i vår komponent, i detta fall som en slags constructorparameter. Vidare har vi kopplat elementets onmouseover och onmouseout händelser till aktuella eventhandlers i komponenten (RollOver() och Restore()).

Hur kopplar vi då detta behavior till HTML elementet? En kakbit!


Hello World!



Nu ser vi tydligt mappningen av rollOverColor attributet som vi läser från komponenten och även hur vi pekar ut rollover.htc filen. Det är viktigt att förstå att det kommer att skapas en ny instans av HTC komponenten för varje HTML element som implementerar detta behavior. Detta gör att vi kan hålla instansdata (state) i komponenten som vi gör med originalColor och originalCursor i exemplet. Från komponenten kan vi alltid nå HTML elementet genom element objektet, element.RuntimeStyle ger oss tillgång till dess style och via denna kan vi enkelt sätta aktuell färg och cursor. Innan jag glömmer det skall jag säga att det givetvis går att koppla fler behaviors till samma element. Detta resulterar ju bara i att ett antal COM objekt (Behavior komponenter) mappas mot samma element. (COM är kärlek, eller hur var det Don Box sa en gång i tiden...)

Det finns även möjlighet till att deklarera events från HTC komponenten som mappas mot events i HTML elementet (som t.ex. onmouseover). Detta kommer vi att använda i drag’n drop komponenten för att aktivera JavaScript som genererar en postback till servern innehållande information om vad som droppades på vad. En demo på detta finns här


Man är inte smartare än den man kopierar

För några år sedan fanns det en lysande kolumn med det anspråkslösa namnet ”DHTML Dude” på MSDN som skrevs av Dave Massey (på bild alltid iförd svarta solglasögon). Jag vet inte om det var .com bubblan som gjorde att man lade ner kolumnen men den var ofta ruggigt bra skriven. Hursomhelst, Dave Massey skrev en artikel om drag’n drop som hette ”Fun with tables”. I detta utmärkta alster skapade han ett HTC behavior för att implementera drag’n drop för gruppering av tabellkolumner i element. Efter lite letande i både min egen hjärna och på MSDN hittade jag länken till artikeln (Fun with tables).

Koden för Daves behavior är anpassat för att arbeta med tabeller och passar kanske inte helt för vår generella drag’n drop implementation men det blev en god start för vårt äventyr. Efter att ha spenderat en halvtimme med att gå igenom Dave Masseys kod kom jag på mig själv med att skriva om stora delar av koden för att kunna anpassa den helt för vår ASP.NET implementation. Det var dock en mycket bra bas för inspiration (trots att den är från 2001!).


Drag’n drop komponenten

För att få en uppfattning om hur resultatet av vårt behavior ser ut har jag lagt upp en demo med lite drag’n drop element på http://www.mickesvarld.se/dragndrop.htm. Om du vill tjuvkika på den kompletta HTC komponenten så finns den på http://www.mickesvarld.se/dragndrop.htc.

Jag har implementerat vår ASP.NET WebControl som ett
element och sätter därför begränsningen att vi bara kan koppla detta behavior till
taggar, det är dock bara att göra liten justering för att även andra element skall fungera med drag’n drop. Man skall kunna koppla detta behavior till valfritt
element på HTML sidan och så skall HTC komponenten vara smart nog att sköta resten. Alla
element som har ett attribut som heter droptarget fungerar som möjliga element att släppa drag’n drop element på. Om vi släpper ett element på ett element som inte har detta attribut så händer ingenting, men om attributet är där så skjuter vi en onDropped event. Jag har även lagt in ett beteende för att markera element som är droptargets med en röd ram när vi drar ett element över dem. Droptarget element behöver inte använda vårt behavior utan det är en uppgift för vårt element som draggas att känna av om elementet under är ett droptarget.


Interface och initiering

Om vi tittar på interfacet till vår komponent så binder vi dokumentets oncontentready event till vår Init() metod med hjälp av ATTACH. Detta gör att när dokumentet är färdigladdat så kommer vår Init metod att anropas. Vidare deklarerar vi två publika events OnDragOver och OnDropped, OnDropped kommer att triggas när vi släpper elementet över ett droptarget, jag lämnar till er att gissa när onDragOver avfyras.







I Init metoden försäkrar vi oss om att elementet som använder behavior komponenten är av typen DIV samt kopplar dokumentets onmouseup, onmousemove, onselectstart samt det aktuella elementets onmousedown event till metoder i vår komponent. På detta sätt kommer det att göras anrop in i varje instans av denna komponent när vi utför händelser som påverkar vår drag’n drop funktionalitet.


function Init()
{
if(element.tagName!="DIV")
{
alert("Dragndrop behaviour by mickesvarld.se is only available for DIV tags");
}
element.runtimeStyle.cursor = "hand";
element.document.attachEvent("onmousemove",onMouseMove);
element.document.attachEvent("onmouseup",onMouseUp);
element.document.attachEvent("onselectstart",onSelect);
element.attachEvent("onmousedown",onMouseDown);
}


Det som initierar en drag’n drop event är givetvis när vi får en mousedown event på ett av våra drag’n drop element. Denna event triggar ett anrop in till onMouseDown i vår komponent som dynamiskt skapar ett DIV element som kommer att följa muspekaren så länge vi inte släpper det. Lägg märke till att vi kan nå elementet som triggade eventen genom e.srcElement.


function onMouseDown(e)
{
this.IsDragged = true;
var src = e.srcElement;
var c = src;
objDragItem = document.createElement("DIV");
objDragItem.ID = "dropElement";
objDragItem.innerHTML = src.innerHTML;
objDragItem.style.height = DRAGGED_ELEMENT_HEIGHT;
objDragItem.style.width = DRAGGED_ELEMENT_WIDTH;
objDragItem.style.background = DRAG_BACKGROUND_COLOR;
objDragItem.style.borderColor = DRAG_BACKGROUND_BORDER_COLOR;
objDragItem.style.fontColor = src.currentStyle.fontColor;
objDragItem.style.position = "absolute";
objDragItem.selectIndex = src.selectIndex;
objDragItem.style.borderStyle = "solid";
objDragItem.style.borderWidth = "1px";
objDragItem.style.filter = "alpha(opacity=80)"
objDragItem.style.display = "none";
src.insertBefore(objDragItem);
}


När vi draggar elementet kommer metoden OnMouseMove köras. Denna metod verifierar att vi har initierat en drag’n drop process och sätter det nyskapade drag’n drop elementets x och y positioner till muspekarens. Metoden trackTarget(element) har jag skapat för att göra boxbaserade kollisionstester för att se om vi har element med droptarget attribut under oss. Om vi har detta markerar vi detta element med en röd ram samt triggar en event som kan tas emot med en eventhandler i HTML elementets tag.


function onMouseMove(e)
{
if(!IsDragged || !objDragItem) return;
var intTop = e.clientY + element.document.body.scrollTop;
var intLeft = e.clientX + element.document.body.scrollLeft;
objDragItem.style.pixelTop = intTop;
objDragItem.style.pixelLeft = intLeft;
resetSelected();
var target = trackTarget(e);
if(target!=null)
{
var objEvent = createEventObject();
objEvent.result = target;
dragOverID.fire(objEvent);
target.style.borderColor = SELECTED_BORDER_COLOR;
}

if(objDragItem.style.display == "none")
{
objDragItem.style.display = "";
}
}


När vi släpper elementet kommer metoden onMouseUp köras. Denna kollar om vi är över ett element som är ett droptarget (med hjälp av metoden trackTarget()). Om detta är fallet så triggas en OnDropped event. Syntaxen för att trigga en event kan se lite knepig ut men det är egentligen ganska enkelt. Skapa ett EventObject med hjälp av createEventObject, koppla eventargument med hjälp av result och avfyra med fire. dropID är i detta fall vår publikt deklarerade event.


function onMouseUp(e)
{
if(!IsDragged) return;
var target = trackTarget(e);
if(target!=null)
{
var objEvent = createEventObject();
objEvent.result = target;
dropID.fire(objEvent);
}
this.IsDragged = false;
objDragItem.removeNode(true);
objDragItem = null;
resetSelected();
}


Detta är i stort sett all kod som behövs för att hantera ett drag’n drop behavior för HTML element. Det som tillkommer är kod för att räkna ut koordinater för icke absolut positionerade HTML element samt att overrida OnSelect för att inte kunna markera text i de element vi skall dragga.


Koppla komponenten till elementet

Ok, det var inte så hårigt, hur får vi nu igång detta från vår HTML? Detta görs som sagt med en enkel koppling i style attributet enligt följande:



News Control



Här ser vi också hur vi kopplat en eventhandler för vår skapade event onDropped. Genom att vi deklarerat denna i komponenten får vi automatiskt tillgång till aktuell event från elementet. På detta sätt går det även att ”overrida” inbyggda eventhandlers som onmouseover vilket kan vara användbart ibland. Alltså, när vi droppar ett element över ett droptarget kommer onDropped eventen triggas. I taggens eventhandler gör vi ett anrop till getDropped och skickar med aktuellt element samt argumentet från eventen (elementet som vi droppat på). getDropped skriver bara ut lite information om vad som hänt till ett debug element enligt följande:


function getDropped(dropElement,container)
{
document.getElementById("debug").innerHTML = dropElement.id + " dropped in " + container.id;
}


Hur skapar vi då ett droptarget element? Sätt bara attributet droptarget på vilket
element som helst enligt följande:



Detta är ett vanligt DIV element som agerar droptarget




Slutord

Att implementera en generell HTC komponent för drag’n drop är inte alls speciellt komplicerat. Vi har nu skapat en behaviorkomponent som kan kopplas till våra element genom style attributet. Koden är kapslad och vi har inte skräpat ner HTML koden med allt för mycket med JavaScript. Vi är dock bara halvvägs på vår resa, nästa moment blir att skapa ASP.NET kontrollen som skall använda detta behavior. Detta beskrivs dock i nästa artikel där vi skapar en ASP.NET WebControl från grunden som kapslar in allt detta. På detta sätt kan vi droppa en kontroll på designytan i Visual Studio.net och automatisk få drag’n drop stöd utan att behöva bry oss om vare sig JavaScript eller behaviors.

All kod för denna artikel kan laddas ner från http://www.mickesvarld.se/dragndrop.zip


Nästa artikel, ASP.NET kontrollen

Nu är det dags att börja leka med kontroller i ASP.NET. Om ni har frågor, förslag på förbättringar eller något annat går det bra att maila mig.

Är ni nyfikna på koden för ASP.NET kontrollen som nästa artikel kommer att baseras på, går det bra att tjuvkika på http://www.mickesvarld.se/mvdragndrop.zip där det färdiga komponentprojektet ligger.

Hoppas att vi ses i nästa artikel och ha en lysande dag i solen/regnet!
/Mikael Olsson [info@mickesvarld.se]
Upp

0 Kommentarer

Skriv en kommentar på artikeln

Ditt betyg på artikeln



Kommentar:





Nyligen

  • 09:09 Vill du köpa medicinska tester?
  • 12:47 Vem beviljar assistansen – kommune
  • 14:17 Någon med erfarenhet av hemstädnin
  • 14:14 Bör man använda sig av en båtförme
  • 14:12 Finns det någon intressant hundblo
  • 14:25 Tips på verktyg för att skapa QR-k
  • 14:23 Tips på verktyg för att skapa QR-k
  • 20:52 Fungerer innskuddsbonuser egentlig

Sidor

  • Hem
  • Bli bonusmedlem
  • Läs artiklar
  • Chatta med andra
  • Sök och erbjud jobb
  • Kontakta oss
  • Studentlicenser
  • Skriv en artikel

Statistik

Antal besökare:
Antal medlemmar:
Antal inlägg:
Online:
På chatten:
4 569 153
27 952
271 704
1 004
0

Kontakta oss

Frågor runt konsultation, rådgivning, uppdrag, rekrytering, annonsering och övriga ärenden. Ring: 0730-88 22 24 | pelle@pellesoft.se

© 1986-2013 PelleSoft AB. Last Build 4.1.7169.18070 (2019-08-18 10:02:21) 4.0.30319.42000
  • Om
  • Kontakta
  • Regler
  • Cookies