Come ottenere un ItemsSource per aggiornare il suo legame?
Domanda
Ho una vista che mostra una casella di riepilogo associata a GetAll () :
<DockPanel>
<ListBox ItemsSource="{Binding GetAll}"
ItemTemplate="{StaticResource allCustomersDataTemplate}"
Style="{StaticResource allCustomersListBox}">
</ListBox>
</DockPanel>
GetAll () è una proprietà ObservableCollection nel mio ViewModel:
public ObservableCollection<Customer> GetAll
{
get
{
return Customer.GetAll();
}
}
che a sua volta chiama un metodo del modello GetAll () che legge un file XML per riempire ObservableCollection .:
public static ObservableCollection<Customer> GetAll()
{
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
XDocument xmlDoc = XDocument.Load(Customer.GetXmlFilePathAndFileName());
var customerObjects = from customer in xmlDoc.Descendants("customer")
select new Customer
{
Id = (int)customer.Element("id"),
FirstName = customer.Element("firstName").Value,
LastName = customer.Element("lastName").Value,
Age = (int)customer.Element("age")
};
foreach (var customerObject in customerObjects)
{
Customer customer = new Customer();
customer.Id = customerObject.Id;
customer.FirstName = customerObject.FirstName;
customer.LastName = customerObject.LastName;
customer.Age = customerObject.Age;
customers.Add(customer);
}
return customers;
}
Tutto funziona perfettamente TRANNE quando l'utente passa a un'altra vista, modifica il file XML e torna a questa vista dove i vecchi dati continuano a essere visualizzati .
Come posso dire a questa vista di " aggiornare i suoi collegamenti " in modo che mostri i dati effettivi.
Mi sembra di andare su WPF qui con troppa metafora HTML / HTTP, sento che c'è un modo più naturale per far sì che ObservableCollection si aggiorni da solo, da qui il suo nome, ma questo è l'unico modo che posso ottenere l'utente per essere in grado di modificare i dati in un'applicazione WPF al momento. Quindi l'aiuto a qualsiasi livello è apprezzato qui.
Soluzione
Un ItemsControl
richiede il suo binding una volta e memorizza nella cache il riferimento in seguito.
Se il contenuto dell'oggetto di raccolta viene modificato e implementa INotifyCollectionChanged
(come ObservableCollection
), raccoglierà qualsiasi oggetto aggiunto o rimosso.
Ora, se si desidera che l'associazione fornisca un nuovo oggetto raccolta al ListBox
, è possibile avere il modello di vista implementare INotifyPropertyChanged
e sollevare PropertyChanged
, passando GetAll
come nome della proprietà.
Ciò avrà l'effetto di avvertire l'associazione che il valore della proprietà è cambiato (esiste un nuovo ObservableCollection
pronto per essere ritirato), che fornirà al ListBox
, che rigenererà i suoi articoli.
Quindi, finché effettui le modifiche dalla tua app, lavorando sul ObservableCollection
restituito da GetAll
, puoi aggiungere e rimuovere e l'elenco rimarrà sincronizzato. Quando desideri raccogliere modifiche esterne (potresti avere un pulsante di aggiornamento da qualche parte o un punto naturale in cui ha senso ricaricare l'intero file), puoi fare in modo che il tuo modello di visualizzazione rilasci l'evento PropertyChanged
, che chiamerà automaticamente il getter della proprietà, che chiamerà il metodo statico, che restituirà una nuova raccolta fresca.
Nota Nitpicker: perché dai nomi di metodo alle proprietà?
Altri suggerimenti
La riga sotto funziona come quando rimuoviamo per aggiungere un oggetto nella raccolta:
CollectionViewSource.GetDefaultView(CustomObservableCollection).Refresh();
Conserva un riferimento al tuo ObservableCollection
e all'ora dell'ultima modifica del file XML al momento del caricamento. Ogni volta che la finestra diventa attiva, controlla la data e l'ora sul file del disco. Se è cambiato, cancella e popola nuovamente ObservableCollection
. La GUI ascolta automaticamente gli eventi di modifica da ObservableCollection
e si popola automaticamente quando modifichi il contenuto della raccolta.