Click here to Skip to main content
15,887,175 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
So, here's the thing. In a WPF application, I am populating a BindableCollection (see: Caliburn.Micro[^] ) from the ViewModel constructor.

Here's the constructor:

C#
public UsersViewModel(IUsersUoW uow, IEventAggregator eventAggregator) : base(uow, eventAggregator)
{
    DisplayName = "Users";
    Users = new BindableCollection<User>(_uow.userrepo.FetchAll());
}


In short, _uow is my Unit of Work and userrepo is my repository. So, this actually populates the property Users which is bound to a Combobox in my View. There's a SelectedUser property which indicates the chosen item of the ComboBox. Now, there's a load of Textbox in view which display various properties of SelectedUser. One can edit the properties by editing the text in TextBox.

Now, in order to save the changes, I have a method, like so:

C#
public void Modify()
{
    var currentuser = _uow.userrepo.Find(SelectedUser.ID);
    currentuser.addr = Address;
    //save other properties
    _uow.userrepo.Update(currentuser);
    _uow.Complete();
    Status = "Modified!";
}


The problem is, this change is being properly saved in the DB, but when I change the selected item in ComboBox to some other item, and then change it back to the item which I edited, the stale data is displayed.

The Update method of the repository is:

C#
virtual public void Update(T updatedentity)
{
    _ctx.Set<T>().Attach(updatedentity);
    _ctx.Entry(updatedentity).State = EntityState.Modified;
}


What I have tried:

One way to alleviate this problem is to repopulate the ComboBox once the modification is made. But that seems to kludgy to me.

What is the standard protocol to avoid stale datum like this? Should I make the property Users like this?

C#
public BindableCollection<User> Users => new BindableCollection<User>(_uow.userrepo.FetchAll());


In this case, I think there would be a performance hit, since every time I access the ComboBox, the repository would be accessed.
Posted
Updated 23-Jun-17 9:39am
v2

So the problem that I think you are having is the fact that you are modifying the entry in the database, but you are not updating the entry in the collection itself.

In your Modify() function you are are fetching the current user from the database, not the collection itself. I would try to fetch the current user from the collection, modify that "User" and then use that to modify the entry in the repository. You would also have to remove the item from the collection and then add the modified entry back into the collection.

Also, be careful using
= new BindableCollection<User>(_uow.userrepo.FetchAll());
each time you go to fetch, because
new
can break your binding. I always try to intialize collections bound to the view only one time in the constructor.

Also, I like BindableList because you can turn off raise events do work turn back on the events and reset the bindings. I find it works well with large datasets as well.

Hope this helps!
 
Share this answer
 
Comments
Sabyasachi Mukherjee 26-Jun-17 11:37am    
Thank you, I just turned my Collection into a calculated property, and calling NotifyPropertyChanged() on the collection whenever it changes does the job perfectly.
This is what I found about the BindableCollection class on:
SynchronizedObservableCollection and BindableCollection | Atomic Blography[^]
Quote:
most commonly it will be fed an ObservableCollection
So it seems you need to use ObservableCollection.
 
Share this answer
 
Comments
Sabyasachi Mukherjee 22-Jun-17 6:50am    
BindableCollection inherits ObservableCollection under the hood. I used BindableCollection because I am using Caliburn.Micro.
RickZeeland 22-Jun-17 7:01am    
Maybe you can follow the steps outlined here: https://github.com/Caliburn-Micro/Caliburn.Micro/tree/master/samples/setup/Setup.WPF

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900