Drag&Drop můžeme využít v řadě případů. Představme si například situaci, kdy máme webovou aplikaci, na kterou se dají nahrávat obrázky. Uživatel může tyto obrázky nahrát standardně přes nějaký dialog a nebo může využít funkcionalitu Drag&Drop. Tedy může přetáhnout soubory ze svého lokálního počítače přímo do aplikace. Druhá varianta bude rozhodně pohodlnější.
Pokud chceme, aby komponenta fungovala jako místo, kde se dá daný soubor “upustit” (Drop), pak nastavíme vlastnost AllowDrop na hodnotu true. Tím říkáme, že komponenta je připravena přijmout soubor, který na ní přetáhneme (Drag). Z komponenty se stává cíl přesunu(Drop Target). Tuto vlastnost podporují všechny komponenty typu UIElement. Nastavením této vlastnosti se nám zpřístupní čtyři události, které můžeme dále využít.
Jednotlivé události jsou:
V drtivé většině případů si vystačíme s událostí Drop.
Jediným podporovaným formátem je datový formát FileDrop. To se velmi liší od technologie WPF, kde datových formátů je celá řada. V dalších verzích Silverlightu je však plánováno toto množství zvýšit.
Každá událost obsahuje parametr typu DragEventArgs. DragEventArgs obsahují vlastnost Data, která zpřístupňuje přetáhnuté objekty. Tuto vlastnost, která je typu IDataObject, využijeme pouze v případě události Drop. V jiných událostech může být přístup do vlastnosti Data ukončen výjimkou(SecurityException).
Dobrým zvykem je na začátku zkontrolovat, zda-li přesunutý objekt je typu, který očekáváme. Momentálně je tato podmínka bezpředmětná kvůli jedinému podporovanému formátu FileDrop. V budoucích verzích bychom ale na to neměli zapomenout.
if (e.Data.GetDataPresent("FileDrop"))
Pokud chceme získat přesunuté objekty, využijeme k tomu metodu GetData(string format). Pole objektů, které se nám vrátí z metody GetData, můžeme přetypovat na pole typu FileInfo. Jeden objekt typu FileInfo odpovídá jednomu přetáhnutému souboru. Z objektu FileInfo lze získat další důležité informace jako je jméno souboru, velikost apod.
FileInfo[] droppedFiles = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
Jak bylo na začátku zmíněno, tak jediným podporovaným formátem je formát typu FileDrop. Nemůžeme tak přetahovat například adresáře.
Drag&Drop nám nebude fungovat v režimu Full-Screen či v módu windowless. Na platformě Macintosh tak budeme muset obejít tento nedostatek pomocí patřičné HTML DOM události. Ale to taky nemusí znamenat stoprocentní funkcionalitu v jiném prohlížeči.
Pokud nemáme aplikace v režimu zvýšené důvěryhodnosti (Elevated-Trust), pak nejsme schopni zjistit cestu k souboru resp. adresář, kde se soubor nachází. Každý takový pokus skončí výjimkou(SecurityException).
V naší aplikaci budeme mít objekt typu Canvas, který bude sloužit jako cíl našeho přesunu (DropTarget). Na Canvas budeme moci umisťovat obrázky s příponou JPG nebo JPEG. Ostatní formáty nebudou podporovány.
V XAMLu si vytvořím objekt typu Canvas, který budeme mít vlastnost AllowDrop nastavenou na true. Tím se z našeho Canvase stane objekt, který je schopný obsloužit přetáhnutý soubor.
<Canvas x:Name="LayoutRoot" AllowDrop="True" Background="AntiqueWhite" />
Nyní tomuto objektu přidáme událost Drop.
<Canvas x:Name="LayoutRoot" AllowDrop="True" Background="AntiqueWhite" Drop="LayoutRoot_Drop" />
Přepneme se do dané metody, která je vyvolána události Drop a napíšeme aplikační kód pro obsluhu "upuštěného" souboru.
V první řadě otestujeme, zda-li přesunutý objekt odpovídá našemu požadovanému typu. Bez této podmínky bychom se docela obešli, ale je dobrým zvykem tuto podmínku použít pro pozdější verze Silverlightu, kde datových formátů bude větší množství.
if (e.Data.GetDataPresent("FileDrop"))
{
}
Nyní je třeba získat pole přetáhnutých objektů, které přetypujeme na pole typu FileInfo[]
FileInfo[] droppedFiles = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
Nyní toto pole můžeme projít, například pomocí cyklu foreach. My si každý objekt převedeme na objekt typu Image, který následně vložíme na plochu Canvasu.
Před samotným zpracováním jednotlivých objektů je zapotřebí zkontrolovat, zda-li s daným objektem chceme pracovat. V našem případě budeme pracovat pouze s obrázky s příponou JPG nebo JPEG. Proto budeme kontrolovat příponu přesunutého objektu. Příponu zjistíme pomocí vlastnosti Extension.
foreach (FileInfo droppedFile in droppedFiles)
{
if (droppedFile.Extension.Equals(".jpg", StringComparison.InvariantCultureIgnoreCase) ||
droppedFile.Extension.Equals(".jpeg", StringComparison.InvariantCultureIgnoreCase))
{
}
}
Nyní přidáme kód pro převedení objektu FileInfo na objekt Image. Obrázek bude "upuštěn" na místo, kde byl naposledy kurzor myši. To zařídíme pomocí vlastnosti Margin. Následně obrázek přidáme do Canvasu.
FileStream fileStream = droppedFile.OpenRead();
{
BitmapImage bi = new BitmapImage();
bi.SetSource(fileStream);
Image img = new Image()
{
Source = bi,
Margin = new Thickness(e.GetPosition(LayoutRoot).X, e.GetPosition(LayoutRoot).Y, 0, 0),
Width=100
};
LayoutRoot.Children.Add(img);
}
Celý kód obsluhující metody vypadá následovně:
private void LayoutRoot_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("FileDrop"))
{
FileInfo[] droppedFiles = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
foreach (FileInfo droppedFile in droppedFiles)
{
if (droppedFile.Extension.Equals(".jpg", StringComparison.InvariantCultureIgnoreCase) ||
droppedFile.Extension.Equals(".jpeg", StringComparison.InvariantCultureIgnoreCase))
{
FileStream fileStream = droppedFile.OpenRead();
{
BitmapImage bi = new BitmapImage();
bi.SetSource(fileStream);
Image img = new Image()
{
Source = bi,
Margin = new Thickness(e.GetPosition(LayoutRoot).X, e.GetPosition(LayoutRoot).Y, 0, 0),
Width = 100
};
LayoutRoot.Children.Add(img);
}
}
}
}
}
Do Canvasu přetáhněte obrázek s příponou JPG nebo JPEG. Obrázek bude vložen na místo, kde byl naposledy kurzor myši. Aplikace umožňuje přetáhnutí více obrázku, ale “vykreslen” bude jen jeden. Je to z toho důvodu, že aplikace nemá připravenou logiku pro obsluhu více přetáhnutých obrázků. Můžeme například použít StackPanel pro rozmístění nebo jinou logiku, která bude splňovat naše požadavky.
Působí jako Microsoft Student Partner a pracuje jako vývojář v jedné nadnárodní firmě. Zajímá se o webové technologie a počítačovou grafiku. Pozornost také věnuje hernímu průmyslu
email: davidb@devedu.cz
web: www.aglight.cz