The setup of the solution is a little bit complicated and restricts my options.
There is a project that contains all the GUI components; in it resides a control that contains a list of 'Project' items that each contains a list of 'Document' items. Initially both of these lists were implemented as ObservableCollections.
Project and Document are defined in a separate project, one that does not have access to System.Windows
One of the critical functions of the program generates a Document within a background thread (because it is slow and time-consuming); this Document needs to be added to a Project's Documents collection.
Since the document is being generated in a background thread, that thread cannot add the document to the collection - a NotSupportedException is generated.
There are several ways to extend ObservableCollections to be thread-safe - unfortunately all of the ones that I have seen so far rely on System.Windows.Threading.Dispatcher, which I cannot use due to (2).
I have discovered that I cannot use INotifyPropertyChanged on a list and must use a collection implementing INotifyCollectionChanged - basically ObservableCollection again. I'm not sure if it's a good idea to implement an extension of a List object when there are so many different methods that modify it, and what's to say it wouldn't have the same issues as ObservableCollection?
Using an explicit UpdateSourceTrigger on the binding does not look feasible, given that the Document is in a HierarchicalDataTemplate, and in any case passing the binding to the Project object looks to be a bit ugly.
Any suggestions?
Create the document on the background thread but use a callback on the primary thread to add it to the ObservableCollection (assuming the ObservableCollection is created on the primary thread).
Related
I have lots of entities with nested List<> in each.
For example, I have BaseEntity which has List<ColumnEntity>.
ColumnEntity class has List<Info> and so on.
We are working with a WPF UI, and we need to track all changes in every List of BaseEntity. It is implemented by instantiating a new ObservableCollection based on the needed list, and with binding to that ObservableCollection.
What are the pros and cons changing all these nested Lists to ObservableCollections? So we can track all changes in BaseEntity itself without reassigning each list of BaseEntity to modified bound ObservableCollection?
Assuming that methods specific to List are never used.
Interesting question, considering that both List and ObservableCollection implement IList<T> there isn't much of a difference there, ObservableCollection also implements INotifyCollectionChanged interface, which allows WPF to bind to it.
One of the main differences is that ObservableCollection does not have AddRange method, which might have some implications.
Also, I would not use ObservableCollection for places where I know I would not be binding to, for this reason, it is important to go over your design and make sure that you are taking the correct approach in separating layers of concern.
As far as the differences between Collection<T> and List<T> you can have a look here
Generic Lists vs Collection
It depends on exactly what you mean by this:
we need to track all changes in every List of BaseEntity
Would it be enough to track changes to objects already in the list? Or do you need to know when objects are removed from/are added to/change positions within the list?
If a list will contain the same items for their whole lifetime, but the individual objects within that list will change, then it's enough for just the objects to raise change notifications (typically through INotifyPropertyChanged) and List<T> is sufficient. But if the list will contain different objects from time to time, or if the order changes, then you should use ObservableCollection<T>.
So while the differences may be interesting (and a previous poster has already covered those), typically you won't have that much of a choice - either you need ObservableCollection<T> or you don't.
List represents a strongly typed list of objects that can be accessed by index. It provides methods to search, sort, and manipulate lists. The List class is the generic equivalent of the ArrayList class. It implements the IList generic interface using an array whose size is dynamically increased as required.
ObservableCollection is a generic dynamic data collection that uses an interface "INotifyCollectionChanged" to provide notifications when items get added, removed, or when the whole collection is refreshed.
Read more about it in this link: http://www.codeproject.com/Articles/42536/List-vs-ObservableCollection-vs-INotifyPropertyCha
One more important difference is you can access ObservableCollection only from thread on which it was created where as list can be accessed fromany thread.
I see no problem with that, other than a very marginal performance overhead.
Note that if you modify the internal Lists directly, you are not notified about changes. Also if the objects which are contained in the ObservableCollection are modified you are not notified. Notification occurs only, if elements are added, replaced, removed or moved.
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!
"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).
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.
Using MVVM in a Silverlight project, I would like to be able to take advantage of the INotifyPropertyChanged interface by using ObservableCollections as the source of the data for a Master/Detail configuration. For the source of the Master list, I would like to use an ObservableCollection that retrieves a minimum number of fields from my database to minimixe loading time, and a different ObservableCollection for my Detail view that includes all fields for editing. Doing this with two different ObservableCollections seems to defeat the INotifyPropertyChanged advantage of using ObservableCollection since the changes are being made to a different ObservableCollection than the one used for the Master List. Is there a way to minimize data loading time for the list and still take advantage of INotifyPropertyChanged?
ObservableCollections notify upon changes in the collection - as in add/remove. They do not handle properties within the objects. The objects themselves have to implement INotifyPropertyChanged.
Objects added to the collections are added by reference. That means that if you update the object...it is updated. It won't make any difference which/how many lists contain the object.
I have asked this question on MSDN forums as well ...
http://social.msdn.microsoft.com/Forums/en/wpf/thread/4493988a-9bd8-48fe-aff0-348502136a80
I need to know that why Microsoft suggests that BindingList is not properly supported in WPF...
What is it that doesnt work with BindingList in WPF? I find it pretty useful as it is. So far I personally have not found BindingList any slower or a having more load on memory.
Plus WPF ItemsControls, ItemsTemplates, Styles, Hierarchies work great with BindingLists too. They are equally observable.
Being a hardcore WPF developer myself and an ObservableCollection fan, my faith is getting shaken by a been-there-done-that BindingList....
Why should I use ObservableCollection over BindingList?
(keeping aside INotifyPropertyChanged which both have to implement for item property changes)
This may be of interest:
http://www.themissingdocs.net/wordpress/?p=465
most important paragraphs:
But the implementation does not scale, it is slow, it performs terribly with larger lists. If your element type supports INotifyPropertyChanged, every time one of those elements raises the property changed event the entire list is walked to work out the index in the list of the item which raised the event! I was in shock when I first realised this. You see BindingList is truly just a rather thin wrapper over Collection, so there is no metadata associated with each entry, all of the binding of the element PropertyChanged event is directed to a single handler, and all it gets given is the source and the name of the changed property, so there is no way to include the NewIndex parameter in ListChangedEventArgs without doing a search. (By default this search even uses the default object comparator, so if you happen to have two different but sometimes equal objects in your list, enjoy the results…)
Another side note – AddNew, the other feature which BindingList has which Collection does not – also does not scale. It has to use IndexOf to find out where in the list the newly added item ended up in case it needs to cancel the add, because it supports auto sorting in derived types. (BindingList does not support auto sorting itself…)
I'm implementing a C++/CLI class library that does some low-level device-related stuff and exposes a few managed classes. This library is about to be utilized by a few C# WPF projects.
One of the classes (called CalibrationRecord) consists of a few public properties, and some of them are collections, currently implemented as generic Lists. One of the WPF project has to be able to edit those collections (i.e. implement CRUD operations).
I'm confused whether it would be better to:
A. Implement those collections as ObservableCollections and be able to use them directly from WPF bindings
B. Add another layer in the client app/another DLL and wrap CalibrationRecord in ObservableCalibrationRecord, where collections are ObservableCollections and properties implement INotifyPropertyChanged
I think that B is a "cleaner" solution because this way my class lib has no knowledge of WPF-related interfaces and classes, however, there would be plenty of additional work to implement this layer, and it would be just plain boring boilerplate code, so A seems tempting.
Which solution would you recommend? Or maybe I'm missing some simpler solution?
Personal anecdotes / opinion only here - but I would recommend Option B as well. ObservableCollections in your Model objects can be overkill - the ObservableCollection can raise a lot of notifications that you may not need (as the collection may not be viewed at that time) and seems to blur the business code with your UI code.
One issue I ran into personally while using a similar setup to your Option B, where the data is stored in both a List and in an ObservableCollection, is whether or not you want a copy of the List data in your ObservableCollection or the actual model data object itself. Obviously if you have the actual data in the ObservableCollection, than as the user updates the model object it will be refelected in your List; however, you can run into some design constraints where the Model object needs NotifyPropertyChanged handling, etc. - which can defeat some of the purpose of seperating the two. Otherwise, you have to take the objects in your ObservableCollection and synchronize them back to the List.
I ended up going with the synchronization approach, although that took a bit of extra work when the user was finished with their edits. In the end, the seperation between the two kept the UI editing code delineated from the business operational code / objects, which was worth it.