Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - [MVVM]Drag & Drop file
Forum - C# / VB.NET - [MVVM]Drag & Drop file

Pagine: [ 1 2 3 ] Precedente | Prossimo
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 20:14
Domenica, 01/09/2013
Salve, mi ritrovo in un form WPF con un listview che deve accertare il drop di file, nessun problema, è un operazione di facile gestione, ma ho bisogno che le operazioni siano gestite all'interno del viewmodel, mi potreste indirizzare sulla strada della soluzione. Grazie in anticipo

PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 21:36
Domenica, 01/09/2013

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 0:24
Lunedì, 02/09/2013
Grazie ma quell'articolo non parla di drag & drop dall'interno del form?
Comunque ho provato con l'eventToCommand
Codice sorgente - presumibilmente Plain Text

  1. <i:Interaction.Triggers>
  2.                 <i:EventTrigger EventName="Drop">
  3.                     <cmd:EventToCommand Command="{Binding FooCommand}" PassEventArgsToCommand="True" />
  4.                 </i:EventTrigger>
  5.             </i:Interaction.Triggers>


Codice sorgente - presumibilmente VB.NET

  1. private RelayCommand _dropFile;
  2.         public RelayCommand dropFile
  3.         {
  4.             get
  5.             {
  6.                 return _dropFile ?? (_dropFile = new RelayCommand(
  7.                     () => {
  8.                         MessageBox.Show("drop");
  9.                     }
  10.                 ));
  11.             }
  12.         }


Ma niente, mi sapete aiutare?

PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 10:31
Lunedì, 02/09/2013
Hai controllato che il binding sia corretto?

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 15:14
Lunedì, 02/09/2013
Cavolo, ho modificato il codice una quarantina di volte in un ora, ho lasciato un errore non indifferente, grazie!
Sono poco esperto di event to command, questo è il primo che faccio, c'è un modo piu elegante per farlo? e mi potreste spiegare come recuperare l'oggetto droppato
Grazie ancora

Edit:
Codice sorgente - presumibilmente VB.NET

  1. public RelayCommand dropFile
  2.         {
  3.             get
  4.             {
  5.                 return new RelayCommand(() => {
  6.                     MessageBox.Show("Drop");
  7.                 });
  8.             }
  9.         }


Ho modificato cosi. A mio parere è decisamente con meno fronzoli... Ma perche MVVM non puo avere una sintassi semplice...

Ultima modifica effettuata da Roby94 il 02/09/2013 alle 16:04
PM Quote
Avatar
Dedalux (Member)
Pro


Messaggi: 103
Iscritto: 15/12/2010

Segnala al moderatore
Postato alle 17:31
Lunedì, 02/09/2013
La soluzione che ti ha consigliato tasx risolve il tuo problema, ed è semplice da usare.

L'EventToCommand non ti aiuta in questo caso dato che non credo l'EventTrigger fornisca sender ed eventargs da passare come parametri al command, e comunque in tal caso andresti un po contro ai principi di MVVM.

In poche parole povere, datti un'occhiata al link della prima risposta. :k:

P.S. sarebbe buona regola non usare la classe MessageBox in MVVM, ma questo è legato più ad una questione di unit test quindi se vuoi, e finchè non ti da problemi, fallo pure.

Ultima modifica effettuata da Dedalux il 02/09/2013 alle 17:34
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 2:25
Martedì, 03/09/2013
Codice sorgente - presumibilmente VB.NET

  1. public RelayCommand<DragEventArgs> dropFile
  2.         {
  3.             get
  4.             {
  5.                 return new RelayCommand<DragEventArgs>(e =>
  6.                 {
  7.                     Console.WriteLine("Drop");
  8.                     string[] files = (string[])e.Data.GetData(DataFormats.FileDrop, true);
  9.                     if (files != null)
  10.                     {
  11.                         foreach (string file in files)
  12.                         {
  13.                             this.images.Add(new Image(file));
  14.                         }
  15.                     }
  16.                 });
  17.             }
  18.         }


Guarda sono riuscito a risolvere cosi dopo diversi tentativi, e mi sembra parecchio più ordinato... Ma te lo voglio chiedere per espandere la mia conoscenza, Perché ritieni che andrebbe contro hai principi del MVVM, io questa logica me la sono trovata quasi imposta quindi non ne conosco i principi troppo bene.
E per i messagebox si lo so fanno parte del namespace form :( ma non so proprio quale sia l'equivalente in WPF e quindi continuo ad usarlo, e non solo per debug.
Comunque per dire la mia ritengo che MVVM in molti casi semplifichi la vita del programmatore con una logica di facile gestione, ma ritengo anche che abbia molti fronzoli inutili, per fare un paio di esempi, l'aggiornamento dei valori bindati mediante RaisePropertyChanged che non capisco, oppure il fatto di non poter bindare una funzione ad un evento e dover fare tutto quello strano giro con RelayCommand.. parlo da ignorante in materia ma secondo me si poteva scegliere una strada ancora piu semplice

PM Quote
Avatar
Dedalux (Member)
Pro


Messaggi: 103
Iscritto: 15/12/2010

Segnala al moderatore
Postato alle 19:10
Martedì, 03/09/2013
Se questa soluzione funziona mi interesserebbe sapere come fai a passare come parametro al RelayCommand il DragEventArgs relativo all'evento.

Per i principi di MVVM i puristi assoluti vedono i riferimenti del ViewModel a istanze di oggetti della View come il diavolo vede l'acqua santa.
Io non sono a questi livelli, ma ho preferito dirtelo per completezza.

Per la MessageBox non è il fatto che si trovi nel namespace Forms, non ha importanza, il fatto è che nel caso tu avessi bisogno di effettuare degli unit test, ti ritroveresti a dover rispondere ad ogni finestrella, bloccando l'automatismo del processo, che per applicazioni sufficientemente grandi potrebbe diventare eterno.
Di solito si usa l'implementazione di un'interfaccia iniettata tramite Dependency Injection che a runtime è la classe normale, mentre in fase di test è una fasulla che invece di mostrare la finestra ritorna direttamente Yes, No, Cancel, True, False, Null o quello che è, così il test fa tutto da solo.

Per INotifyPropertyChanged è l'interfaccia essenziale per WPF e MVVM.
Il binding si incolla ad una proprietà, ma se non ci fosse quest'interfaccia non verrebbe mai avvisato del cambiamento del valore, è proprio PropertyChanged che dice all'interfaccia di refreshare i binding su di essa.
Si tratta di un'interfaccia convenzionale: quando viene creato il binding, il motore databinding verifica se il datacontext implementa INPC, e in tal caso, sottoscrive all'evento PropertyChanged esposto dall'interfaccia. Quando tu fai PropertyChanged(() => this.[Proprietà]) non fai altro che sollevare un evento PropertyChanged, che l'interfaccia raccoglierà per poi agire di conseguenza.

Non puoi bindare una funzione ad un evento perchè il binding è una cosa, e la sottoscrizione è un'altra.
Per questo si usano behaviors, converters & co..

Il RelayCommand è nato per unire execute e canexecute dell'interfaccia ICommand in una sola classe, per comodià, altrimenti i binding sarebbero il doppio (per i comandi).

Sinceramente non trovo scomodi i commands, e nemmeno propertychanged, ma se trovi soluzioni ancora più semplici fammelo sapere!! :k:

Ultima modifica effettuata da Dedalux il 03/09/2013 alle 19:17
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 19:47
Martedì, 03/09/2013
Guarda sono contento quando saltano fuori questi scambi di idee e opinioni. Ti espongo le mie idee da esterno al MVVM visto che lo uso da veramente poco per poterne avere una panoramica completa.
Per partire ti posto il codice per il drop
Codice sorgente - presumibilmente Plain Text

  1. <i:EventTrigger EventName="Drop">
  2.                     <cmd:EventToCommand Command="{Binding dropFile}" PassEventArgsToCommand="True" />
  3.                 </i:EventTrigger>


Codice sorgente - presumibilmente VB.NET

  1. public RelayCommand<DragEventArgs> dropFile
  2.         {
  3.             get
  4.             {
  5.                 return new RelayCommand<DragEventArgs>(e =>
  6.                 {
  7.                 });
  8.             }
  9.         }


Il compito di passare l'oggetto DragEventArgs dopo varie ricerche l'ho assegnato a PassEventArgsToCommand="True"
Qui vorrei partire con la mia affermazione sul bind degli eventi, io la vedrei molto piu semplice con un attributo all'interno del tag oggetto che indica quale funzione lanciare al verificarsi dell'evento, molto vicina al classico usato nei windows form, lo trovo un metodo piu immediato e pulito, un attributo e una funzione punto.
Codice sorgente - presumibilmente Plain Text

  1. <Button Content="Cancel" Click="{Binding click}"/>


nel ViewModel
Codice sorgente - presumibilmente C# / VB.NET

  1. private void Click(object sender, RoutedEventArgs e)
  2.         {
  3.  
  4.         }


Il messagebox io lo trovo comodo in fase di debug per poter sospendere l'esecuzione del programma per poter analizzare le suo sfaccettature un lato alla volta e non ritrovarmi sommerso da linee di console che mi dicono cosa a funzionato o cosa no. Ma questo credo che dipenda molto dalle abitudini dello sviluppatore, non credo che si possa definire un metodo universale.
Per la tematica RaisePropertyChanged non capisco perché al cambio di una variabile bindata ad un determinato campo bisogni notificare questo per apportare cambiamenti all'interfaccia, nei mie programmi infatti lascio che sia il programma in automatico a farlo
Codice sorgente - presumibilmente C++

  1. private bool _run { get; set; }
  2.         public bool run
  3.         {
  4.             get
  5.             {
  6.                 return this._run;
  7.             }
  8.             set
  9.             {
  10.                 this._run = value;
  11.                 this.RaisePropertyChanged(() => this.run);
  12.             }
  13.         }


In questo modo al cambio di run non dovrò notificare manualmente il suo valore modificato ed esso si aggiornerà da solo nel programma.
Scusa se mi ripeto ma lo faccio per non creare fraintendimenti, quello che ti ho accennato sopra lo dico in base a come io vorrei vedere un sistema come MVVM evolversi per eliminare molte parti di codice che a mio parere appesantiscono la lettura e la scrittura da parte di uno sviluppatore

PM Quote
Pagine: [ 1 2 3 ] Precedente | Prossimo