Wpf: “Drag & Drop” Behavior, embrionale.
La gestione del drag & drop è quindi un ottimo candidato per divertirci con gli attached behavior, nome figoso per le ormai legacy attached properties.
Quello che vogliamo ottenere è questo:
ergo poter definire, data ad esempio una ListView, ma funziona su qualsiasi UIElement, quale sia il dato (utilizzando il potentissimo strumento di Binding) da “draggare” e quale sia, opzionale, il DataFormat del “dragged object”.<ListView HorizontalAlignment="Stretch" SelectedItem="{Binding Path=Selection}" behaviors:DragDropManager.DataObject="{Binding Path=Selection}" behaviors:DragDropManager.DataObjectType="mySampleType" ItemsSource="{Binding Path=TestList}">
E sul drop target limitarci a fare:
Utilizzando un ICommand come “target” del drop. Utilizziamo un ICommand perchè si sposa molto bene con il concetto di “drop”, il drop è fondamentalmente fatto da 2 fasi:<Border Grid.Column="1" Margin="10" behaviors:DragDropManager.OnDropCommand="{Binding DropCommand}" HorizontalAlignment="Stretch" AllowDrop="True" VerticalAlignment="Stretch" Background="Gainsboro" />
- una fase di analisi, durante di DragOver, per capire se la “roba” che stiamo draggando possa essere droppata sul target –> ICommand.CanExecute( DragOverArgs e );
- una fase in cui effettivamente, se il DragOver ha dato feedback positivo, i dati vengono droppati –> ICommand.Execute( DropArgs e );
L’attached behavior DragDropManager si occupa di tutte le fasi essenziali della gestione del Drag & Drop e per ora lo fa in maniera decisamente minimale, ma lo fa.this.DropCommand = DelegateCommand.Create() .OnCanExecute( o => { var e = ( DragOverArgs )o; return e.Data.GetDataPresent( "mySampleType" ); } ) .OnExecute( o => { var e = ( DropArgs )o; var data = e.Data.GetData( "mySampleType" ); //Use "data"... } );
Quello che viene fatto è decisamente semplice (fonti: D&D #1 e D&D #2):
- Sull’elemento sorgente (aka DragSource):
- vengono agganciati i 2 eventi fondamentali: PreviewMouseMove e PreviewMouseLeftButtonDown, non stiamo prendendo in considerazione l’eventualità che i pulsanti del mouse siano invertiti, in cui gestiamo l’inizio dell’operazione di D&D;
- Sull’elemento destinazione (aka DropTarget):
- Settiamo a true la proprietà AllowDrop;
- Agganciamo gli eventi DragOver e Drop, nel primo recuperiamo una reference al command e invochiamo CanExecute, mentre nel secondo invochiamo Execute;
.m