heltonbiker
heltonbiker

Reputation: 27605

ObservableCollection and Repository pattern in MVVM - How to relate them, and a case for the "Update" method

My Desktop WPF application has a repository (of type Person) which resides in the Model layer, and is called by a ViewModel which has a PersonList property which is databound to a DataGrid.

When I open my Application, the list is shown by default. During initialization, the following code applies:

public class PersonScreenViewModel : ViewModelBase
{
    PersonRepository _person_repository;

    public ObservableCollection<Person> PersonList { get; set; }

    public PersonScreenViewModel() {

        _repositorio_pacientes = new RepositorioPacientes();

        PersonList = new ObservableCollection<Person>(_person_repository.GetAll());
    }

    // ... ///
}

My doubts are based on some difficulty to understand how to implement "Save / Update" method(s).

Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ]". So, the most logical thing would be to databind the repository itself to the DataGrid. That could be done if I created a class which inherit from ObservableCollection and implements repository logic. Currently, what I do is take a copy of the repository items, using _repo.GetAll(), and work in that copy, having to commit back after my changes are done.

Specifically, my workflow involves selecting a row in the DataGrid, changing some properties of the selected object, and commiting these changes, expecting that the same object is persisted with the new property values.

Usually, if you take an object in a collection and modify it, you don't need to "update" anything, since you already changed the object itself.

The question is: "How can I data bind my view to the repository itself? Should the repo inherit from ObservableCollection? How is it supposed to be done? Is some part of my reasoning flawed?"

It is important to say that my application is not data-oriented, the Person class is very basic (POCO marked as [Serializable], with a few properties), and my repository uses plain XML serialization and the filesystem structure.

Thanks for reading!

Upvotes: 6

Views: 7779

Answers (2)

Sheridan
Sheridan

Reputation: 69987

In my personal opinion, what you are currently doing is correct... it is generally good practice to have some separation between the various layers of your application; Models, View Models, Views and DataAccess (sometimes combined into Models). Having said that, it really depends on your application... it might not be worth doing this on small applications as it adds a lot of code and time to set up and maintain.

However, the main reasons for providing this separation (called separation of concerns) is to enable unit tests to be able to test the individual layers without concerning the other layers. For example, if we wanted to write unit tests for our view models, we wouldn't want to test their functionality on the actual data objects in the database. If we have this separation (through the use of interfaces) then we can simply mock up data objects to use during these tests.

Another reason, although less common in practice, is to enable whole layers to be 'swapped out' without affecting the code in the other layers. Examples of this would include changing the database used in the application, or maybe changing the views from a desktop application into web pages in a web application. If we have separate layers, then these changes won't affect the other layers.

So to answer your question directly, I wouldn't bind your views to the repositories at all... keep your current separation. After all, how long does it take to copy a collection sourced from the database into a view collection property?

UPDATE >>>

I'm not sure that I fully understand the question in your comment. I'm guessing that you are binding your PersonList property in your view model to the DataGrid.ItemsSource property to display the data. Any changes made in the DataGrid should affect the items in your PersonList. If you were to add a 'Save' Button, then you could update the database in that click or command handler.

If you were enquiring how to find out which elements had been changed, there are several methods for accomplishing this. There is a good tip in the How to get only modified Items from WPF Data Grid post here, but I prefer to use a duplicate collection and just compare them to find the changed elements (you'd need to implement the Equals method for this to work).

Please let me know if that does not answer your question.

Upvotes: 2

123 456 789 0
123 456 789 0

Reputation: 10865

"Every text about the Repository pattern tells that "the repository should behave like a collection of [ entities | domain objects ".

What you originally have is sort of correct. First of all ObservableCollection works perfectly with the View because every add/update/delete will automatically propagate back to the user interface. If you implemented it with repository, then you would have to go call the database reload the control bound to your repository

"How can I data bind my view to the repository itself? Should the repo inherit from ObservableCollection? How is it supposed to be done? Is some part of my reasoning flawed?"

  • You don't want to data bind the Repository to the DataGrid itself, because you lose caching and every time the user loads the user control you always have a trip back to your database.
  • You don't want to inherit a repository to an ObservableCollection, ObservableCollection has more overhead vs simple IEnumerable given you already database returned you a collection already.
  • You always don't want ObservableCollection as your collection for your data because it is expensive. A simple enumerable of data is enough depending on your scenario (Read-only data).

Upvotes: 2

Related Questions