What is the fastest way to update my DataContext binding to my WPF usercontrol so that it shows changes in the object it is bound to in the view?
The best option is to make your DataContext object implement INotifyPropertyChanged. Make any collections implement INotifyCollectionChanged (ie: use an ObservableCollection<T> instead of List<T>, etc).
If you do this, then the bindings will automatically stay up to date, with no effort on your part.
Binding an ObservableCollection (which implements a specific interface) with objects that implement INotifyPropertyChanged will immediately show changes to their values in the front end or backend whenever you make changes, as long as the binding modes are set to two way binding.
This question here appears to be very similar.
Silverlight: How to force binding after setting the DataContext property
If you don't want to implement the INotifyProperty, you can use my answer and just set the datacontext again
Related
I'm creating a simple database application in C# WPF using MVVM as Relay Commands and databinding. For in-memory storage of database content I use ObservableCollection, which is binded to the Datagrid as follows:
<DataGrid ItemsSource="{Binding Path=Softwares, Mode=OneWay}" SelectedItem="{Binding Path=SoftwareSelection, Mode=TwoWay}">
when the item is selected user can chose to edit it. For editation a form is opened with a bunch of textboxes with the data of given entity. All the fields are validated using IDataErrorInfo, unless all textboxes are valid, the ok button is not enabled, and therefore no changes can be saved to the collection and to the database.
Here is how the example textbox looks like:
<TextBox Text="{Binding Name, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>
But the tricky part is, in case I change some values in textboxes and then close the window, the new values are propagated to the ObservableCollection, which I don't want to. Do you have any idea, how to prevent such behaviour? I would like the databinding work only after clicking the button. Otherwise the databindng works well, so as the button (dis/en)abling and reflecting changes to the database and to the collection after clicking. Both views are serviced by different ViewModels, data between views are passed by firing events.
I tried to add to the DataGrid UpdateSourceTrigger=Explicit to the ItemsSource binding, but didn't help. Perhaps, I'm missing some application logic?
Thank you very much for your help.
This is where most WPF developers make mistakes of assumptions!
In MVVM dirty data can be stored in the ViewModel and that's what the layer of VM is for! It mimics the View from Model's perspective and because View is in error, the ViewModel would also be in the error. Thats perfectly valid.
So having said that, the question remains
How will you NOT allow the temporary / dirty data to flow to your
ObservableCollection?
Two ways...
If your ObservableCollection is specific to your model class (say MyItem) then if your Model class (MyItem) is an Entity class \ DAL class \ NHibernate class create a wrapper of MyItem class called ViewModelMyItem and then instead of ObservableCollection<MyItem> use ObservableCollection<ViewModelMyItem>.
This way dirty data from your View would be inside ViewModelMyItem and it can only be legitimately flown back to your model class (MyItem) ONLY when Save button is clicked. So that means in Save Command's Execute() delegate you can copy \ clone the ViewModelMyItem's properties into Item's properties, if validations in ViewModelMyItem are fine.
So if Item is an EntityType class / NHibernate class / WCF client model class, it would always only valid data as ViewModelMyItem is filtering the temporary / dirty information upfront.
You could use Explicit binding model. It stops the TwoWay data to flow back to the sorce Item unless BindingExpressions.UpdateSource() is explicitly called.
But according to me, this defeats MVVM in straightforward way because ViewModel will not have what UI is showing! Still however you can use *Attached Behavior * to govern explicit binding by staying in MVVM space!
Let me know if this helps!
You're better off putting the code into the domain object's property setter. Then synchronize with the visuals by triggering the NotifyPropertyChanged handler.
More on this topic:
http://msdn.microsoft.com/en-us/library/ms743695.aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
Setting the Binding Mode to Explicit should require you to call the binding expressions UpdateSource() method to send changes back to your model. Because you only mentioned that you set Explicit on the DataGrid's binding, I'm guessing you only need to make sure that you have that mode explicitly set on any property that is being bound directly back to your model. Such as your TextBox's Text Binding, in the case above. That will likely fix your problem but require you to call UpdateSource() on each target's BindingExpression one way or another.
If you're using one of the mainstream ORM's (EF, Linq to SQL, etc), then chances are your Entities automatically implement INotifyPropertyChanged and INotifyPropertyChanging. Because you are sharing a reference to your single instance, all changes in your edit will be reflected in your main view and anything else Binding to that instance. As a dirtier alternative, you can just create a separate instance of the same type and manually copy the values back over when the window's dialog result is true.
The first approach requires you to manually update the bindings, the second approach requires you to manually update the values from the Edit's instance.
With some more code, I can help with your specific approach.
I'm new with MVVM and I'm stuck...
I have a ListBox in the MainWindow. The ListBox contains Items of type WhatEverViewModel which are displayed by DataTemplates. The user can interact with these items and the WhatEverViewModel has several DependencyProperties which may change during interaction.
The question I have is:
How can I elegantly react (in the MainWindowViewModel) to changes of DependencyProperties of the CURRENTLY SELECTED WhatEverViewModel. I personally would implement some events in the WhatEverViewModel and when the SelectedItem of the ListBox change, I would attach to the events of the currently selected WhatEverViewModel. But I think in MVVM there might be a more elegant way to solve this...
Thank you.
Make CurrentWhatEver a property of your MainWindowViewModel and bind the Listbox.SelectedItem property on it. This way, MainWindowViewModel knows when the selected WhatEver changes and can register/unregister to events it's interested in.
communication between viewmodel can be done in several ways.
Messenger/Mediator like the one form MVVM Light
Eventstuff like the one from PRISM
or simply use harcoupling and subscribe to the events from the WhatEverViewModel in your mainviewmodel.
btw why in hell to you use DependencyProperties in your Viewmodels? simple Properties with INotifyPropertyChanged are the way to go.
one more thing. why you want to react to changes in the SelectedViewmodel(or better what you want to achieve, with the selected viewmodel.)? if you just want to display some information in your view, simply bind the SelectedViewmodel to it. you should specify your question in that way.
EDIT
The WhatEverViewModel has a list which is also bound to a listbox (in
datatemplate) and depending on what I select in the WhatEverViewModel
I want to display some kind of "Configurator" in the MainViewModel. –
JensPfister1 1 hour ago
why not simply bind the SelectedWhatEverViewmodel.SelectedListEntryProperty to your configurator view? can you post some code?
You should implement the INotifyPropertyChanged interface on each of your ViewModels. Then when one of your properties changes call the PropertyChanged event, your views will get notifications that the property has changed (as long as your Binding is correct). If a property is a list or collection make sure that the list is based off an INotifyCollectionChanged.
Add a property for the Selected WhatEverViewModel to your MainWindowViewModel, bind that in your ListBox. Then in your MainWindowViewModel you can hook on to the property changes of your Selected WhatEverViewModel.
For more guidance read:
WPF MVVM INotifyPropertyChanged Implementation - Model or ViewModel
http://blogs.msdn.com/b/soultech/archive/2011/06/07/mvvm-tips-when-implementing-inotifypropertychanged.aspx
Should one bind DataGrid to the
ICollectionView = CollectionViewSource.GetDefaultView(collection)
or to the
ObservableCollection<T> collection; ???
What is the best practice for MVVM and why?
You always bind to an ICollectionView, whether you make it explicit or not.
Assume that we have
var collection = new ObservableCollection<string>();
var collectionView = CollectionViewSource.GetDefaultView(collection);
In this case, binding to collection or to collectionView is one and the same: the binding engine will bind to the default collection view (which is reference equal to collectionView) if you tell it to bind to collection.
This means that the answer to your question is "it makes absolutely no difference".
Just to be totally clear: even if you bind to the collection directly, the binding engine will bind to the default view. Modifying properties of the view such as sort criteria will affect the binding that appears to bind directly to the collection, since behind the covers it's a binding to the default view instead.
However, there is another interesting and related question: should one bind to the default collection view (i.e., to the collection itself, because there's no reason to explicitly bind to the default view) or to another view of the same collection?
Considering that each view has its own notion of current item, sort criteria, etc, it follows that if you intend to have multiple bindings to the same collection, and the bound controls need to have distinct notions of current item, filters and company, then what you want is to explicitly bind to multiple views of the same underlying collection.
ObservableCollection<T> implements INotifyCollectionChanged and will notify the UI when the items in the collection have been changed.
ICollectionView will give you the ability to filter, sort, or group the collection in addition to propogating INotifyCollectionChanged events if the underlying collection implements it.
Either type works well with MVVM as long as you bind to it. Use ICollectionView when you need sorting, filtering, or grouping. Use ObservableCollection<T> directly when you don't.
Just to add to what Jon said. The main difference is, that by using CollectionViewSource.GetDefaultView(collection), you are making you ViewModel dependent on WPF. Many MVVM purists don't like this and this would leave ObservableCollection only valid option.
Other option would be to use ICollectionView and use a class, that implement it, but is not part of WPF itself.
I don't think so it has to do anything with MVVM itself. ICollectionView provides additional features like soring grouping and etc if you need those use IColectionView otherwise simply use ObservableCollection
You would bind to the view if you wish your grid to display the settings applied to the view, e.g. filtering, otherwise the view is redundant.
I have an ObservableCollection that's binded to a WPF ListView, and all the values appear correct. But how can I get a notification when something that has a 2-way binding changes?
Should I use INotifyPropertyChanged just like in Winforms? Or are there better practices to do these?
I saw some people suggesting using dependency properties online, but not sure if that's what should do.
If the class I want to add a property is a DependencyObject, I generally add a DependencyProperty. If the class is a POCO (plain old clr objects), then I implement INotifyPropertyChanged.
In generall, all my business objects are POCOs and therefore I use INotifyPropertyChanged. In the WPF world, I mostly use DependencyObjects (view models, custom controls, UserControls...) and therefore they are DependencyProperties. An exception are ViewModels representing items (to be used as items in an items source). In this case I think DependencyProperties are not very practical (Because Equals() and GetHashCode() of DependencyObjects are sealed and DependencyObject is thread-dependent).
If your class already is a DependencyObject, using DependencyProperties may give you some nice advantages: You don't have to back every value, a powerfull inheritance system, default-values, property changed callbacks per property, value coercion ... (I like DependencyProperties probably more than other people them like :)
Conclusion:
Based on the title of your question: How to get notified when something changes in a WPF window?, my way would be to add a DependencyProperty and not a clr-property because the Window is a DependencyObject. By the way, Visual Studio has a nice Snippet to create DependencyProperties.
There are really two scenarios:
1) Notifying the UI when a piece of data changes-either in the ViewModel or a Model that is bound to some UI elements (usually due to a data binding). In this scenario you'd use INotifyPropertyChanged.
Example: you have a Person object that binds it's Name to a TextBox. Person needs to implement INotifyPropertyChanged and the appropriate code needs to be attached to the Name Property's setter.
2) Creating custom UI elements where you'd want data to be bound. In this case, you'd use custom dependency properties.
Example: you have a custom UI element that spins when a certain condition is met. So you create an IsSpinning dependency property that you can bind to your ViewModel's IsLoading property. The custom control then uses the IsSpinning property to modify its behavior.
I hope that was clear...
You are right. You can use INotifyPropertyChanged or you can implement dependency properties. Personally I prefer INotifyPropertyChanged, it's more light and easyer to implement than dependency property.
I've generally used INotifyPropertyChanged for my data objects.
DependencyProperties can only be implemented on framework elements I believe.
Edit: I take that back... DependencyProperties can only be implemented on DependencyObjects (A FrameworkElement is an example of that as it derives from UIElement which derives from Visual which derives from DependencyObject).
If you have a UserControl, you may wish to implement a Dependency Property so you can Bind that Property (in XAML) to some other property. You could not do this scenario with INotifyPropertyChanged.
i am writing an application that has a viewmodel and a usercontrol that displays
data from this viewmodel. The viewmodel contains an entity "Appointment", and those
appointments have a property "UserName".
When I display the appointments, I want to use a value-converter to get a color for
the user (depending on "UserName"), but the colors are not contained in the entity "Appointment", so I wanted to create a value-converter that uses the entity "User" from the viewmodel.
What is the best way to use another entity from the viewmodel inside the converter?
Is it possible to access the viewmodel from the usercontrol? I tried to place the converter inside my viewmodel-class, but can I access this class from the usercontrol?
I figured out that the following possibilities might work:
Adjust the viewmodel so that each appointment also contains the color. But I don't want to do this because I don't want to mess with the viewmodel.
Set the converter-parameter from the class that also contains the viewmodel at startup. (Does this work?)
Use x:Reference to databind the converter parameter to the viewmodel that is unknown at compile-time.(Is this possible?)
Converter parameter is the way to go.
Why is the viewmodel unknown at compile time?
Bindings are not compile time checked anyway.
Is the UserControl.DataContext being set to an instance of Appointment, you should be able to set the parameter to {Binding UserName} or {Binding Appointment.UserName} depending on exactly what you are setting as the DataContext on the UserControl.
I would suggest that you re-examine your reluctance to modify the view model. The purpose of having a view model in the first place is so that everything that the view needs can be found in one place. Coming up with elaborate value converters to prevent modifying the view model is an approach that gets increasingly unmaintainable the more you do it.