In tutti i precedenti esempi non abbiamo mai definito in maniera esplicita la modalità di Binding, quindi il comportamento predefinito prevede che sarà di tipo TwoWay. Quindi, modificando via codice la fonte dati, l'interfaccia deve automaticamente aggiornarsi.
Per dimostrare questa caratteristica apportiamo alcune modifiche al codice, aggiungiamo due pulsanti sotto la ListBox
, che serviranno rispettivamente per modificare un Team
esistente e per aggiungerne uno nuovo.
<StackPanel x:Name="LayoutRoot"> <ListBox Margin="10" ItemsSource="{Binding}" DisplayMemberPath="Name" /> <Button x:Name="btnEdit" Margin="10" Content="Modifica Team Esistente" Click="btnEdit_Click" /> <Button x:Name="btnAdd" Margin="10" Content="Aggiungi Team" Click="btnAdd_Click" /> </StackPanel>
private List<Team> teams; public Page() { InitializeComponent(); teams = Team.GetAll(); LayoutRoot.DataContext = teams; } private void btnEdit_Click(object sender, RoutedEventArgs e) { teams.First().Name = "Edited Team"; } private void btnAdd_Click(object sender, RoutedEventArgs e) { var newteam = new Team { Name = "HTML.IT Team", CurrentDriver = "Matteo Baglini" }; teams.Add(newteam); }
Eseguendo l'applicazione e cliccando sui due Button
notiamo che in realtà non accade niente di tutto ciò che era previsto. Il motivo è dovuto al fatto che la fonte dati deve essere in grado di notificare al DataContext che sono stato apportate delle modifiche. Per fare ciò dobbiamo agire a livello di singola entità implementando nella classe Team
l'interfaccia INotifyPropertyChanged
ed a livello di collezione utilizzando ObservableCollection
al posto di List
. Il risultato finale sarà il seguente.
public class Team : INotifyPropertyChanged { private string name = String.Empty; public string Name { get { return name; } set { name = value; RaisePropertyChanged("Name"); } } private string currentDriver = String.Empty; public string CurrentDriver { get { return currentDriver; } set { currentDriver = value; RaisePropertyChanged("CurrentDriver"); } } public event PropertyChangedEventHandler PropertyChanged = delegate { }; private void RaisePropertyChanged(string propertyName) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public static ObservableCollection<Team> GetAll() { return new ObservableCollection<Team> { new Team { Name = "Citroen Total World Rally Team", CurrentDriver = "Sebastian Loeb" }, new Team { Name = "BP Ford Abu Dhabi World Rally Team", CurrentDriver = "Mikko Hirvonen" } }; } }
Eseguiamo nuovamente l'applicazione, clicchiamo entrambi i Button
ed il risultato finale sarà quello mostrato in figura: