vediamo se ho capito MVVM...
Quote from Lucio_B on 17/02/2021, 12:03Ho una classe cliente con le sue proprietà Nome, Cognome, ecc
poi ho una window con i vari textbox
normalmente avrei istanziato cliente nel code behind della window, impostato il datacontext sul istanza di cliente e messo nello xaml in binding i vari textbox con le varie proprietà di cliente..
volendo passare a MVVM se ho capito bene devo creare una classe clienteViewModel che mi espone le stesse proprietà di cliente, istanzia cliente al suo interno e i vari getter mi ritornano i valori delle proprietà di cliente
es.
Property Nome as string
Get
return Cliente.Nome
End Getquindi nel code behind della window instanzio clienteViewModel e lo uso come datacontext.
in questo caso posso lasciare il model (cliente) e la View puliti, cioè senza codice (o lo stretto necessario nella view) e tutto l'eventuale codice lo posso mettere nel Viewmodel..
se ad esempio voglio che quando imposto il Comune automaticamente il programma imposti CAP e Provincia prendendoli da una lista, questo codice lo metto nel ViewModel
o anche se mi serve una proprietà "complessa" come per esempio una che mi ritorni l'indirizzo completo formattato (Nome Cognome Via x, y Cap Comune PROV), pure questa la metto nel ViewModel così il model resta pulito (solo dati)
Ho capito giusto?
p.s. in questo caso il notifypropertychange mi basta implementarlo solo nel viewmodel x aggiornare automaticamente i controlli visto che cliente viene caricato solo all'inizio da disco e modificato solo tramite la viewmodel?
Ho una classe cliente con le sue proprietà Nome, Cognome, ecc
poi ho una window con i vari textbox
normalmente avrei istanziato cliente nel code behind della window, impostato il datacontext sul istanza di cliente e messo nello xaml in binding i vari textbox con le varie proprietà di cliente..
volendo passare a MVVM se ho capito bene devo creare una classe clienteViewModel che mi espone le stesse proprietà di cliente, istanzia cliente al suo interno e i vari getter mi ritornano i valori delle proprietà di cliente
es.
Property Nome as string
Get
return Cliente.Nome
End Get
quindi nel code behind della window instanzio clienteViewModel e lo uso come datacontext.
in questo caso posso lasciare il model (cliente) e la View puliti, cioè senza codice (o lo stretto necessario nella view) e tutto l'eventuale codice lo posso mettere nel Viewmodel..
se ad esempio voglio che quando imposto il Comune automaticamente il programma imposti CAP e Provincia prendendoli da una lista, questo codice lo metto nel ViewModel
o anche se mi serve una proprietà "complessa" come per esempio una che mi ritorni l'indirizzo completo formattato (Nome Cognome Via x, y Cap Comune PROV), pure questa la metto nel ViewModel così il model resta pulito (solo dati)
Ho capito giusto?
p.s. in questo caso il notifypropertychange mi basta implementarlo solo nel viewmodel x aggiornare automaticamente i controlli visto che cliente viene caricato solo all'inizio da disco e modificato solo tramite la viewmodel?
Quote from sabrina_c on 18/02/2021, 12:23Direi che fondamentalmente si hai capito bene, però nel viewmodel io metto un istanza di Cliente e all'interno di Cliente implemento INotifyPropertyChanged in modo che le property reagiscono correttamente quando attacco tali property alle textbox dal Viewmodel onde evitare di dover generare 2 classi diverse per lo stesso uso.
Per mio difetto personale, anche tutte le property aggiuntive (indirizzo completo, ecc.) le implemento nella classe Cliente e non nel Viewmodel, il ViewModel è un oggetto che parla con la view e con il model (dal suo nome) e contiene tutte le istanze degli oggetti del model (che possono essere tanti) che utilizzi in una window, ad esempio, nel viewmodel di una Lista clienti, hai bisogno di una ObservableCollection<Cliente> per la lista e di un ClienteCorrente da collegare all'elemento selezionato se vuoi poi chiamare la finestra del dettaglio cliente per il Cliente corrente della lista.
Ti ho confuso a sufficienza?
Chiedi pure tutte le delucidazioni che vuoi
Direi che fondamentalmente si hai capito bene, però nel viewmodel io metto un istanza di Cliente e all'interno di Cliente implemento INotifyPropertyChanged in modo che le property reagiscono correttamente quando attacco tali property alle textbox dal Viewmodel onde evitare di dover generare 2 classi diverse per lo stesso uso.
Per mio difetto personale, anche tutte le property aggiuntive (indirizzo completo, ecc.) le implemento nella classe Cliente e non nel Viewmodel, il ViewModel è un oggetto che parla con la view e con il model (dal suo nome) e contiene tutte le istanze degli oggetti del model (che possono essere tanti) che utilizzi in una window, ad esempio, nel viewmodel di una Lista clienti, hai bisogno di una ObservableCollection<Cliente> per la lista e di un ClienteCorrente da collegare all'elemento selezionato se vuoi poi chiamare la finestra del dettaglio cliente per il Cliente corrente della lista.
Ti ho confuso a sufficienza?
Chiedi pure tutte le delucidazioni che vuoi
Quote from Miky on 19/02/2021, 09:12Riporto la mia esperienza sul commento di Sabrina
All'inizio ero partito ad usare solo ClienteSelezionato, poi ho aggiunto ClienteCorrente per distinguerlo dal primo.
Ma da qui ho cominciato a fare confusione coi i due termini e ad incasinare il codice.
Quindi, per buona pratica, ora uso di base sempre una lista per i Selezionati (anche se inizialmente a prima vista potrebbe essere solo uno) e un oggetto per il Corrente.
Riporto la mia esperienza sul commento di Sabrina
All'inizio ero partito ad usare solo ClienteSelezionato, poi ho aggiunto ClienteCorrente per distinguerlo dal primo.
Ma da qui ho cominciato a fare confusione coi i due termini e ad incasinare il codice.
Quindi, per buona pratica, ora uso di base sempre una lista per i Selezionati (anche se inizialmente a prima vista potrebbe essere solo uno) e un oggetto per il Corrente.
Quote from Lucio_B on 20/02/2021, 11:14Grazie a entrambi.. ora credo di avere le idee un po' più chiare,
io immaginavo il viewmodel come una classe che "riveste" il model (instanziandolo al suo interno) e ne espone le singole proprietà, per ogni model.proprietà c'è una corrispondente viewmodel.proprietà(che va a leggere/scrivere in model.proprietà).
invece è più simile al "vecchio" code behind della view..
instanzia il model ed espone il model stesso (viewmodel.model)
diciamo che serve "solo" per spostare tutto il codice al di fuori della view così da separare e rendere indipendenti il lavoro del designer (che si occupa della view) e del programmatore (che si occupa del viewmodel e che dovrà fornire al designer solo i nomi delle proprietà da collegare nella view).forse stavolta l'ho capita 🙂
Grazie a entrambi.. ora credo di avere le idee un po' più chiare,
io immaginavo il viewmodel come una classe che "riveste" il model (instanziandolo al suo interno) e ne espone le singole proprietà, per ogni model.proprietà c'è una corrispondente viewmodel.proprietà(che va a leggere/scrivere in model.proprietà).
invece è più simile al "vecchio" code behind della view..
instanzia il model ed espone il model stesso (viewmodel.model)
diciamo che serve "solo" per spostare tutto il codice al di fuori della view così da separare e rendere indipendenti il lavoro del designer (che si occupa della view) e del programmatore (che si occupa del viewmodel e che dovrà fornire al designer solo i nomi delle proprietà da collegare nella view).
forse stavolta l'ho capita 🙂
Quote from Lucio_B on 20/02/2021, 13:38ci ho provato ma qualcosa non va...
creo la classe viewmodel che instanzia model e ne espone la proprietà
nel code behind:
Public Property ClienteViewModel As New ClienteViewModel
datacontext=mee fin qui tutto funziona
se nello xaml scrivo:
<StackPanel >
<TextBox Width="600" Text="{Binding Path=ClienteViewModel.Cliente.Nickname}" />
</StackPanel>Funziona,
ma se invece imposto ClienteViewModel come DataContext di tutto lo stackpanel che ospita i vari textbox..
<StackPanel DataContext="ClienteViewModel">
<TextBox Width="600" Text="{Binding Path=Cliente.Nickname}" />
</StackPanel>non funziona più.. con questo errore di binding
BindingExpression path error: 'Cliente' property not found on 'object' ''String' (HashCode=-1467934314)'. BindingExpression:Path=Cliente.Nickname; DataItem='String' (HashCode=-1467934314); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')
perché object 'string' ?? non dovrebbe far riferimento a ClienteViewModel ?
ci ho provato ma qualcosa non va...
creo la classe viewmodel che instanzia model e ne espone la proprietà
nel code behind:
Public Property ClienteViewModel As New ClienteViewModel
datacontext=me
e fin qui tutto funziona
se nello xaml scrivo:
<StackPanel >
<TextBox Width="600" Text="{Binding Path=ClienteViewModel.Cliente.Nickname}" />
</StackPanel>
Funziona,
ma se invece imposto ClienteViewModel come DataContext di tutto lo stackpanel che ospita i vari textbox..
<StackPanel DataContext="ClienteViewModel">
<TextBox Width="600" Text="{Binding Path=Cliente.Nickname}" />
</StackPanel>
non funziona più.. con questo errore di binding
BindingExpression path error: 'Cliente' property not found on 'object' ''String' (HashCode=-1467934314)'. BindingExpression:Path=Cliente.Nickname; DataItem='String' (HashCode=-1467934314); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')
perché object 'string' ?? non dovrebbe far riferimento a ClienteViewModel ?
Quote from Miky on 20/02/2021, 15:53Non sono sicuro del codice che hai scritto, comunque
<StackPanel DataContext="ClienteViewModel"> // ClienteViewModel qui e' una string 🙂
dovrebbe essere:
<StackPanel DataContext="{Binding ClienteViewModel}">
Assegnare però il datacontext allo StackPanel non credo abbia molto senso, anche se si puo' fare.
Il datacontext lo assegnerei alla Window (o comunque al controllo "radice") che contiene lo StackPanel.
Poi magari nel tuo caso va bene così.
Non sono sicuro del codice che hai scritto, comunque
<StackPanel DataContext="ClienteViewModel"> // ClienteViewModel qui e' una string 🙂
dovrebbe essere:
<StackPanel DataContext="{Binding ClienteViewModel}">
Assegnare però il datacontext allo StackPanel non credo abbia molto senso, anche se si puo' fare.
Il datacontext lo assegnerei alla Window (o comunque al controllo "radice") che contiene lo StackPanel.
Poi magari nel tuo caso va bene così.
Quote from Lucio_B on 20/02/2021, 20:13ammazza al {binding}.. ecco perché mi dava quell' errore
assegnavo il Datacontext allo StackPanel perché ci avevo messo dentro solo la parte che gestisce il cliente selezionato, lasciando la lista dei clienti nel code behind..
ora ho messo tutto nel viewmodel e assegnato alla radice ( una Page nel mio caso) e funziona benissimo.
grazie delle dritte !!
ammazza al {binding}.. ecco perché mi dava quell' errore
assegnavo il Datacontext allo StackPanel perché ci avevo messo dentro solo la parte che gestisce il cliente selezionato, lasciando la lista dei clienti nel code behind..
ora ho messo tutto nel viewmodel e assegnato alla radice ( una Page nel mio caso) e funziona benissimo.
grazie delle dritte !!