In MVVM pattern, how to notify all properties of the view model has changed? I don' t want to call all notifypropertychanged event of all properties.
I have an entity class and in view model I wrote all of the public fields of the entity as public properties. I want to rebind new entity and just write a single line of code to notify that all properties has changed?
Thanks for your help.
Just raise the PropertyChanged event with an empty string as the property name :
OnPropertyChanged(String.Empty);
Ok what I understood from your question is this..
View <> ViewModel <> Entity (with a bunch of properties)
View is bound to ViewModel, which delegates to Entity. You now want to replace the backing entity and signal the view to refresh to update to the newer entity.
I'd suggest implementing an indexer in the ViewModel which takes in a string (the name of the backing property). The ViewModel can be used as a cache if required, delegating to the backing entity only on a miss.
When you replace the entity, the viewModel clears its cache and fires NotifyPropertyChanged (in the indexer set) with String.Empty or null. Which I learned today, indicates all properties have changed.
This way you don't create n delegating properties in the ViewModel. A google search result shows that it has been tried at least once with success.
Related
I'm migrating from Linq-to-SQL to Entity Framework (4.4), using Database First with a DbContext. I'm wondering whether the following behavior is normal:
using (var e = new AgendaEntities()) {
var store = e.Stores.First();
var office = e.Offices.Create();
office.Store = store; // Set association
Console.WriteLine(office.StoreID); // shows Guid.Empty, expected store.ID!
}
In L2S, setting the Store association to an entity would also update the StoreID key. In EF, this doesn't seem to be happening. This is regardless of whether the entities are new or loaded from the context.
When I SaveChanges, it saves correctly and the StoreID is updated to match office.ID, but why does this only happen after the save?
Is there something I'm missing, or am I now supposed to keep foreign keys in sync manually?
Solution Edit:
This is called property fixup, and used to be done automatically by the generated proxies. However, with DbContext this is no longer the case. According to this Connect issue, this is by design.
Hello,
The DbContext template actually doesn't generate classes that will be used as change tracking proxies - just lazy loading proxies (which don't do fix-up). We made this decision because change tracking proxies are complex and have a lot of nuances that can be very confusing to developers.
If you want fix-up to occur before SaveChanges you can call myContext.ChangeTracker.DetectChanges.
~EF Team
An alternative is to call DbContext.Entry(entity), which will sync up the entity. This is described in this article: Relationships and Navigation Properties under "Synchronizing the changes between the FKs and Navigation properties"
No. Entity framework does this for you. Read Relationships and Navigation Properties for more information.
By assigning a new object to a navigation property. The following
code creates a relationship between a course and a department.
If the objects are attached to the context, the course is also
added to the department.Courses collection, and the
corresponding foreign key property on the course object is set to the
key property value of the department.
course.Department = department;
But as you observed, this only happens after you call SaveChanges or one of the other actions mentioned in the "Synchronizing the changes between the FKs and Navigation properties" portion of the document linked above.
If you are using POCO entities without proxies, you must make sure
that the DetectChanges method is called to synchronize the related
objects in the context. Note, that the following APIs automatically
trigger a DetectChanges call.
DbSet.Add
DbSet.Find
DbSet.Remove
DbSet.Local
DbContext.SaveChanges
DbSet.Attach
DbContext.GetValidationErrors
DbContext.Entry
DbChangeTracker.Entries
Executing a LINQ query against a DbSet
If this is not happening at all, my guess is that you haven't properly defined StoreID as the foreign key of the navigation property Store.
I am using the Service Layer --> Repository --> Entity Framework (Code-First) w/POCO objects approach, and I am having a hard time with updating entities.
I am using AutoMapper to map my Domain Objects to my View Models and that works good for getting the data, no how do I get that changes back into the database?
Using pure POCO objects, I would assume that there is no sort of change tracking, so I see my only option is to handle it myself. Do you just make sure that your View Models have the EXACT same properties as your Domain Objects? What if I just change a field or two on the View Model? Won't the rest of the fields on the Domain Object get overwritten in the database with default values?
With that said, what is the best approach?
Thanks!
Edit
So what I am stumbling on is this, lets take for example a simple Customer:
1) The Controller has a service, CustomerService, that calls the services GetCustmoerByID method.
2) The Service calls into the CustomerRepository and retrieves the Customer object.
3) Controller uses AutoMapper to map the Customer to the ViewModel.
4) Controller hands the model to the View. Everything is great!
Now in the view you do some modifications of the customer and post it back to the controller to persist the changes to the database.
I would assume at this point the object is detached. So should the model have the EXACT same properties as the Customer object? And do you have to make hidden fields for each item that you do not want to show, so they can persist back?
How do you handle saving the object back to the database? What happens if your view/model only deals with a couple of the fields on the object?
If you're using EF Code First, i.e: the DbContext API, then you still do have change tracking which is taken care of by your context class.
after making changes to your objects, all you have to do is call SaveChanges() on your context and that will persist the changes to your database.
EDIT:
Since you are creating a "copy" of the entity using AutoMapper, then it's no longer attached to your context.
I guess what you could do is something similar to what you would in ASP.NET MVC (with UpdateModel). You can get the original entity from your context, take your ViewModel (which may contain changed properties) and update the old entity, either manually (just modified properties), or using AutoMapper. And then persist the changes using context.SaveChanges().
Another solution would be to send the model entity as [part of] the ViewModel. This way, you'll have your entity attached to the container and change tracking will still work.
Hope this helps :)
You are absolutely right that with a detached object you are responsible for informing the context about changes in your detached entity.
The basic approach is just set the entity as modified. This works for scalar and complex properties but it doesn't work for navigation properties (except FK relations) - for further reading about problems with navigation properties check this answer (it is related to EFv4 and ObjectContext API but same problems are with DbContext API). The disadvantage of this approach is that all fields in DB will be modified. If you just want to modify single field you still have to correctly fill others or your database record will be corrupted.
There is a way to explicitly define which fields have changed. You will set the modified state per property instead of whole entity. It is little bit harder to solve this on generic approach but I tried to show some way for EFv4 and for EFv4.1.
I agree with #AbdouMoumen that it's much simpler to use the model entities at the view level. The service layer should provide an API to persist those entities in the data store (db). The service layer shouldn't dumbly duplicate the repository lawyer (ie: Save(entity) for every entity) but rather provide a high level save for an aggregate of entities. For instance, you could have a Save(order) in the service layer which results in updating more basic entities like inventory, customer, account.
I'm rather new to WP7 dev and I'm trying to play with data binding. I have an XML file and I want to represent it in a ListBox. I've made a ModelView on which I make a Linq query, the result of which I want to put in a ListBox. I've seen that many examples of DataBinding use the ObservableCollection class. I would like to use Linq to get the results instead of looping row by row, but if I use the IEnumerable instead of ObservableCollection, DataBinding does not work. Is that normal?
Silverlight works on a property changed mechanism to be notified when a property has changed in order to update a data binding. You can either use dependency properties (highly unlikely for a view model) or implement the INotifyPropertyChanged interface in your view model class.
In the case of ObservableCollection, it actually raises the CollectionChanged event when it's contents change (add/remove/insert), which also prompts the data binding to update. In your case, by binding to an IEnumerable, the data binding mechanism doesn't know when the contents has changed because there are no events raised.
If every action results in a new list, then you're not gaining anything by creating an ObservableCollection each time you re-query. So you'll need to implement the INotifyPropertyChanged interface and raise property change notification for yrou IEnumerable property when you re-query.
If you have items to add/remove each time you re-query, then creating an ObservableCollection the first time and then calling Add/Remove on each query will work just fine.
I guess it has to be an IList to work. IEnumerable won't work.
Try adding .ToList() to your LINQ query to convert it to List<T>.
As for ObservableCollection<T>, you need to use it if you plan to change items in that collection so that the UI automatically refreshes itself.
You can create an ObservableCollection from an enumerable by passing it to one of the constructors for the OC.
ObservableCollection<Foo> x = new ObservableCollection<Foo>(enumerable);
Courtesy of Cast LINQ result to ObservableCollection
Of course, this only applies if you want to avoid looping through the records yourself and don't have a reason due to behaviour in the code.
but if I use the IEnumerable instead of ObservableCollection, DataBinding does not work
Using an IEnumerable for your list of data items is not the problem, in fact the definition for the ItemsSource property on the ListBox is:
public IEnumerable ItemsSource { get; set; }
Most likely the issue is that your property is not notifying when its value has changed (use the INotifyPropertyChanged interface).
The ObservableCollection type is a collection that implements INotifyCollectionChanged, so you can easily tell when the collection itself has changed, although this doesn't notify you when the properties on the collection items themselves have changed. It also implements INotifyPropertyChanged, which is most likely why your data binding was working on your property in your ViewModel. The reason why the ObservableCollection is good to use in this case is because you can just add and remove items to the collection to update the list based control, you don't have to rebind it (or rebuild a list).
So if you bind to a IEnumerable<> property, make sure you raise a notification that the property has changed, and be aware that adding/removing individual items will not get reflected automatically in the UI unless you devise a way of notifying that the bound property has changed (which would be a bit of a hack).
I have my MVVM and the model consists of a number of related classes, but for the sake of this question we'll focus on just four.
GrandParentModel, ParentModel, ChildModel and Contact.
These all inherit from ModelBase which has an implementation of INotifyPropertyChanged on it.
So each of the three models has a Contact property. If Child doesn't have a property it is supposed to look to Parent, and if Parent is blank it will look to GrandParent. If the contact changes at the grandparent level I'd like any dependants, ie any sub parents and their children to raise a PropertyChanged event for their Contact too.
I think everything I'm going to do will be supported by the DependencyProperty system, but I don't want to use that as this is my Model, separation of concerns and all that. So I'm putting together a mini implementation, which is all fine.
My question is has anyone been down this path before and is there anything I should be worried about in the future? My Spidey-Senses are tingling and I don't know why.
Thanks
Ian
Edit: The relationship between the objects here is that a grandparent has any number of parents has any number of children. My current model has a property on each which points at the parent (null in the case of a grandparent) and a parent/grandparent has a collection of child objects.
I've been down this path, and it's not pretty. Basically you have to subscribe to the PropertyChanged event of ParentModel from your ChildModel. You have to take care if your child can change parents. Then when you get notified of a change in the parent from the child's point of view, you have to raise your own PropertyChanged event on the child. It gets ugly because you can end up with hanging event handlers that you forgot to clean up.
A better method would be to create your own Model-specific analog to DependencyProperty. Basically in your constructor of ChildModel you "declare" that property Contact delegates to property Contact of object Parent when null. You do that using a little helper class that observes the PropertyChanged event on the ParentModel object and have it execute a PropertyChanged event on the child when appropriate. Also have it watch for the Parent property to change on the child.
You could use the MVVM Light message bus. Have the grandparent and parent all send a message when their Contact property changes. Have the child listen for those messages. When it gets a message, then check to see if it matches its own parent or grandparent, and raise a PropertyChanged event if necessary. This is better than either method above because you don't have to keep track of when your parent or grandparent changes. You're less likely to have bugs. It also uses weak references, so it won't hold on to objects the way event handlers do.
Now what I've been doing is getting away from having my model objects implement INotifyPropertyChanged. I introduced a Presenter layer between my Model and my ViewModel. The Presenter actually constructs a ViewModel out of small ViewModel "widgets" (one widget might be a ChangeValue<T> widget, for instance). I have a rules engine that tells the Presenter how to compose a ViewModel out of widgets for a given Model. The Presenter handles all user input (basically executing a lambda against the Model), but since it knows that a user action just took place, it knows that something in the Model might have changed. After the Model action is complete, it copies all of the data from the Model to the ViewModel. The ViewModel inspects the incoming data and raises a PropertyChanged event if the field actually changed. Obviously that's the most compliated way of doing it, but it gives you a really clean Model and neither the ViewModel nor the Presenter contains any Model (domain/business) logic.
I'm after some opinions \ best practice for handling updates to my repository in the following scenario:
I am using EF 4 with the POCO tt templates which creates nice clean clr objects.
For example's sake lets say I have a POCO object name Customer and a ViewModel called CustomerViewModel. CustomerViewModel has a public property for the Customer object which is populated with the POCO Customer object.The view references the Customer object on the CustomerViewModel. So far so good. Everything is displayed as expected.
When it comes time to update the CustomerViewModel is passed back and only the properties that were bound to the view are populated, fair enough.
What I have now is a POCO object that is missing some of the property values which are needed to update via the EF data context. For example, since I did not display the ID in the view, it was not hydrated back into the view model's Customer property. Not really surprising behaviour but I am wondering what the best way to handle this scenario is.
So here is the question:
Would it be better to map the properties that i don't display into hidden fields so that I have the complete POCO object on postback which is ready for updating to the Repository? (I'm thinking there is needles sending of data to and from the client here)
OR should I do a read of Customer before my update(assuming I have the ID) and then update the properties from my view model object. ( is this a needles read on the database ?).
OR is there another may altogether that I am missing.
I realise that maybe there is no one correct answer for this but I'd be interested to hear how others are handling this scenario.
Thanks
I'm going to answer my own question here... maybe it was a silly question but the act of writing it out has made the answer more obvious..
The first option of populating hidden fields is a bad idea for too many reasons!! So I think I'll have to go with doing a read of the customer object on the post back and calling.
TryUpdateModel(customer, "Customer");
Where customer is the freshly read Customer and "Customer" is the property name on the view model.
It seems that this results in more data access than in a classic ASP where the object could have been shoved (rightly or wrongly) into Session !
Anyone care to add their 2c ?