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.
Related
I have an MvxListView that binds to a property on the ViewModel which is a List<MyClass>.
MyClass is a plain old object that has a boolean property named Completed that I've bound to the Checked property of a CheckedTextView in my list view item template.
When I click on the list view item, it invokes a command which calls a DoSomething(MyClass item) method. In the DoSomething method, I set the Completed property to its new value. However, because MyClass is not a ViewModel with RaisePropertyChanged properties, the checked property doesn't get updated in the user interface.
How would I accomplish data binding on this basic POCO to get the user interface to update when the Completed property changes?
How would I accomplish data binding on this basic POCO to get the user interface to update when the Completed property changes?
Xaml/C# style Data-Binding relies on INotifyPropertyChanged - without this the UI has no way to know that it needs to update.
So to get data-binding to work, your MyClass objects can't just be a POCO - it needs to implement INotifyPropertyChanged somehow - e.g. by inheriting from MvxNotifyPropertyChanged or by implementing INotifyPropertyChanged directly (e.g. see http://msdn.microsoft.com/en-us/library/vstudio/ms229614%28v=vs.100%29.aspx)
Aside: MvvmCross does also make other binding patterns possible beyond INotifyPropertyChanged - e.g. see INotifyChanged in FieldBinding in https://github.com/MvvmCross/MvvmCross/wiki/Databinding#rio - but this still requires something more than just POCOs for dynamically updating bindings.
I have a View that contains a GridView object and a ViewModel that the View represents. Now, I'd like to override the controls in that ViewModel so that I keep the same GUI but with different business logic (i.e. contained within the ViewModel). What's the proper way of doing that?
I'd assume it is not as simple as extending the ViewModel since there's the issue with its GUI being represented in the View (which has a XAML component).
Any thoughts?
Thanks.
Edit: Fixed typo
What I tend to do, is create a Base ViewModel Class with the standard UI and Control logic in it.
I then set whichever Functions / Subs I want to control individually to overrideable. But I populate them up with default code, such as The standard Form State (Editting/Adding/Deleting) code. Any I want to force to be Overridden are set to Must Override of course.
Then, I create a Individual View-Based ViewModel, inherit from the Base ViewModel Class, override the methods I require, and set this Individual ViewModel to be the DataContext for the View.
You can switch in which ever ViewModels you like using this method, so long as they all inherit from your base ViewModel class.
I hope this helps!
Please, help me to understand one thing in the MVVM pattern:
For example, I need to display cities on a map.
In ViewModel I have ObservableCollection, that binded to a View ItemsSource.
ObservableCollection contains objects with type "City".
Must "City"-class be inherited from ObservableObject (I use MVVM Toolkit)? Or I should create a wrapper class, inherit it from ObservableObject, in ViewModel create new wrap-objects with data from "City"-objects and add them to the collection?
Thank you!
Assuming that your City class is in your model, and you actually need to know about changes to properties on the city object - then you should create a wrapper for it (i.e. CityViewModel). Your wrapper should listen to events that notify of any changes to the City class, and fire off the relevant Property Change notifications.
Model classes should be designed to fit with the model and should not change to suit your view - the point of having a ViewModel in the first place is to abstract your model from your view. The model should know nothing of the View.
If the properties of your City class dont change, or you dont care if they don change (and you are not a purist) then you could just expose it directly - without inheriting ObservableObject.
(Although I dont use MVVM toolkit, I cant see why in general you would need to inherit ObservableObject just because you are storing the City objects in an ObservableCollection).
The purist view however, is to wrap everything that you bind to and never expose anything from the model directly to the view.
ObservableCollection or ObservableObject has no relation with MVVM model. You can create a MVVM based application without ObservableCollection and ObservableObject (ObservableObject are used when you need to change the values of property of your class but if your application is readonly you dont even need it).
MVVM -
M-Model (business layer) , V-View (GUI), ViewModel- (Context of GUI).
When XAML works on binding. You must need a notification mechanism to notify GUI that something is changed. Now if a collection is changed means you added or removed an item from collection, you need to raise a notification which you dont need if you are working with ObservableCollection. Similarly, if your class City has a property Population which when changes need to notify GUI, that's why need to make an ObservableObject.
Hope it helps..
I am trying to come up with a solution for the following problem:
I have a DateTimeRange class which contains 3 properties:
Start: DateTime
End: DateTime
Length: Length (=End-Start)
This class is used throughout my project as dependency property on various controls. This values are mutable, for example, if the Start changes, the End will be moved with the same offset (keeping the same Length).
My problem is that in code that listens for updates of the range, does not recieve an event when any of the properties have changed, only when the complete object is replaced.
I want to let the DateTimeRange class notify the user that the whole object has changed when a property is changed, not just one property.
I have tried to make DateTimeRange an immutable struct. But this makes two way DataBinding to any of it's properties impossible.
Does anybody have a suggestion how to do this? IMO this problem is very frustrating, as the same problem happens with Margins for example (you cannot bind to Margin.Left of a control).
The framework does not really support this requirement. The approach I would take would be to make DateTimeRange implement INotifyPropertyChanged, raising the event whenever any of its properties change. On a class that has DateTimeRange as a dependency property add / remove handlers for the INotifyPropertyChanged as the property changes. Within your handler for this event you can then perform the action you require.
Note, you could make DateTimeRange a DependencyObject, which would allow you to create two way bindings to its properties.
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