Question

I've got a view which shows a listbox that is bound to GetAll():

<DockPanel>
    <ListBox ItemsSource="{Binding GetAll}"
             ItemTemplate="{StaticResource allCustomersDataTemplate}"
             Style="{StaticResource allCustomersListBox}">
    </ListBox>
</DockPanel>

GetAll() is an ObservableCollection property in my ViewModel:

public ObservableCollection<Customer> GetAll
{
    get
    {
        return Customer.GetAll();
    }
}

which in turn calls a GetAll() model method which reads an XML file to fill the 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;
}

This all works fine EXCEPT when the user goes to another view, edits the XML file and comes back to this view where the old data is still showing.

How can I tell this view to "refresh its bindings" so that it shows the actual data.

It feels like I am going about WPF here with too much of an HTML/HTTP metaphor, I sense there is a more natural way to get ObservableCollection to update itself, hence its name, but this is the only way I can get the user to be able to edit data in a WPF application at the moment. So help on any level is appreciated here.

Was it helpful?

Solution

An ItemsControl requests its binding once and caches the reference thereafter.

If the content of the collection object are modified, and it implements INotifyCollectionChanged (as ObservableCollection does), it will pick up any added or removed object.

Now, if you want the binding to supply a new collection object to the ListBox, you can have your view-model implement INotifyPropertyChanged and raise PropertyChanged, passing in GetAll as the property name. This will have the effect of warning the binding that the property value has changed (there is a new ObservableCollection ready to be picked up), which it will supply to the ListBox, which will re-generate its items.

So as long as you effect changes from your app, working on the ObservableCollection returned by GetAll, you can add and remove and the list will stay in synch. When you want to pick up external modifications (you might have a refresh button somewhere, or a natural point where it makes sense to reload the whole file), you can have your view-model raise the PropertyChanged event, which will automatically call the property getter, which will call the static method, which will return a fresh new collection.

Nitpicker note: why do you give method names to properties?

OTHER TIPS

Below line work same as when we remove to add object in collection:

CollectionViewSource.GetDefaultView(CustomObservableCollection).Refresh();

Keep a reference to your ObservableCollection and the XML file's last-modified time as of the time you loaded it. Whenever the window gets focus, check the timestamp on the disk file. If it's changed, clear and re-populate the ObservableCollection. The GUI is automatically listening for change events from the ObservableCollection and will re-populate automatically when you modify the collection's contents.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top