M-V-VM: master-details (2): let’s move on…
- Abbiamo introdotto il pattern Model View ViewModel partendo dai concetti di base;
- Ci siamo spostati in uno scenario un po’ più complesso;
- Abbiamo piacevolmente divagato su alcuni punti che sono emersi;
- essere in grado di modificare un indirizzo;
- essere in grado di eliminare un indirizzo;
- come tenere traccia dell’elemento selezionato nella lista degli indirizzi?
- come visualizzare i dati dell’elemento selezionato?
- come gestire un’azione, la cancellazione in questo caso?
Tenere traccia di quale sia l’indirizzo selezionato è un’operazione relativamente banale:
Anche se ci pone di fronte ad una prima decisione: chi è responsabile di tenere traccia di quale sia l’elemento selezionato?private AddressViewModel _selectedAddress = null; public AddressViewModel SelectedAddress { get { return this._selectedAddress; } set { if( value != this.SelectedAddress ) { this._selectedAddress = value; this.OnPropertyChanged( () => this.SelectedAddress ); } } }
- PersonViewModel?
- o MainViewModel?
Le modifiche da apportare allo xaml sono altrettanto banali:
Ci limitiamo a chiedere alla ListView di tracciare quale sia l’lemento corrente mettendo in binding la proprietà SelectedItem con la nostra proprietà SelectedAddress.<ListView Grid.ColumnSpan="2" Grid.Row="4" Margin="12" ItemsSource="{Binding Path=Person.Addresses}" SelectedItem="{Binding Path=SelectedAddress}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
Visivamente a questo punto non è cambiato nulla ma se mettiamo un breakpoint sul setter della nostra proprietà al variare dell’elemento selezionato il motore di binding viene da noi a impostare il nuovo valore.
Naturalmente il binding è bidirezionale quindi possiamo preimpostare un SelectedAddress e vedere che la ListView si adegua di conseguenza:
this.SelectedAddress = this.Person.Addresses.FirstOrDefault();
SelectedItem “reverse” binding
Ora che abbiamo un elemento selezionato possiamo introdurre nella nostra vista master-details la porzione di UI per l’editing e ringraziare il motore di databinding di Wpf per averci regalato cotanta potenza:
Potenza che già a designtime, visto che per ora le cose sono molto semplici, ci fa capire che siamo sulla strada giusta:<TextBox Height="23" HorizontalAlignment="Stretch" Text="{Binding Path=SelectedAddress.Street, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Grid.Column="1" Grid.Row="6" /> <TextBlock HorizontalAlignment="Right" Text="Number:" VerticalAlignment="Top" Grid.Row="7" /> <TextBox Height="23" HorizontalAlignment="Stretch" Text="{Binding Path=SelectedAddress.Number, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Grid.Column="1" Grid.Row="7" /> <TextBlock HorizontalAlignment="Right" Text="City:" VerticalAlignment="Top" Grid.Row="8" /> <TextBox Height="23" HorizontalAlignment="Stretch" Text="{Binding Path=SelectedAddress.City, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Grid.Column="1" Grid.Row="8" />
A runtime abbiamo la conferma definitiva:
Cambiando la selezione automaticamente il nostro dettaglio si aggiorna, ma non solo, scrivendo qualcosa nel campo “City”, ad esempio, il valore viene riflesso, real-time, anche nella ListView sempre grazie al motore di DataBinding.
Adesso che abbiamo un elemento selezionabile, tracciabile e modificabile non ci resta che renderlo anche cancellabile… ma direi che oggi ho scritto un’altra volta fin troppo :-)
Sorgenti aggiornati: Mvvm.Application-1.2.zip
.m