I have a user control UC_A that contains a user control UC_B. Each has a different view model as its data context, VM_A and VM_B respectively, both derived from INotifyPropertyChanged.
A command from VM_A changes stuff that affects a property in VM_B. UC_B has a binding to that property. How can I cause the binding to update? I tried OnPropertyChanged in VM_A but it does not do the job.
Any help would be appreciated.
If VM B changes, then the notification must be raised from there to notify UC B.
To add on what #flq said already,
I don't see what's the problem, if you implemented OnPropertyChanged properly it should just work.
i.e. when your View-model-A changes something in the view-model-B - then whatever property is changed in the VM-B should fire off the OnPropertyChanged - from the VM-B - and that'd 'land' into the UC-B lap, as it should.
Related
In my silverlight application I need to send a notification from a ViewModel to a View. In response to it a method on a UI control should be called. I know about 2 ways to accomplish this:
1) Raise an event in the ViewModel and handle it in the View's code behind.
2) Send a message from the ViewModel (using the MVVM Light messaging support) and respond to this message in the View's code behind.
I'd like to know if there is a way to accomplish this without using code in the View's code behind, for instance through some kind of data binding in the XAML?
Please share any ideas.
Additional info about what the View should do when it receives notification from ViewModel
In the XAML of the View I declare an instance of a custom Silverlight grid control which has the following method:
public void FileExportFinished(bool fileExportSucceeded)
I want to call this method from the XAML in response to the notification received from the ViewModel passing a boolean value received with the notification.
Yes...you can do it with the help of a dependency property.
Create a dependency property for that view (Make it boolean type since we just need this property to call another view method).
In its property changed call back, make provisions to call your required view method.
Then bind the DependencyProperty with a propert in ViewModel.
So when you need the view to be updated, just set the binded Property mentioned above, this will fire the property changed call back of Dependency property and form there your required view method will be called.
why not simply use a Property in your viewmodel and a DataTrigger in your xaml?
if you want some kind of dialog popup you can use a dialogservice. you should really add what you wanna do to your question. what should happen in your view when the notification arrive?
btw Messenger is for viewmodel-viewmodel communication, so thats not an option.
TestScenario:
I've got a Control with a DependencyProperty A.
I've got a ViewModel with a property A that I bind against the Control's A-Property using the OneWayToSource Binding. The Binding is updated explicitly by the Control.
I switch out the bound ViewModel instance at runtime, thereby changing the underlying Source of my Binding.
When this happens I would like an Event to fire that tells my control that I can now update the value of its DependencyProperty A. The reason is, that as soon as you change the bound ViewModel, the DependencyProperty A's DefaultValue is written to the Source.
Instead, I would like the control to come up with a proper value and update the source manually.
One might think that just listening to the DataContextChanged event solves the problem. However, when this Event gets fired, the Source of the BindingExpression still points to the old ViewModel.
The only hackaround I can come up with, is to use Dispatcher.BeginInvoke with the DispatcherPriority.DataBind priority in the EventHandler of DataContextChanged.
It works, but does not feel clean to me.
I am looking for an event in the Binding-class that notifies me about changes of the Source... however I cannot find one.
Thank you
Perhaps I'm not understanding the question completely, but can you just use the NotifyOnSourceUpdated or NotifyOnTargetUpdated properties (and the corresponding SourceUpdated or TargetUpdated events)?
I've seen many Tutorials about the MVVM-Patern but I still don't get why I need to get a Dependency-Property or an INotiyfyPropertyChanged-Property if I want to send information from the ViewModel back to the View.
Dependency properties provide built in change notification for when a property changes which means WPF knows when a controls value has changed.
Your ViewModel types do not, by default, provide any mechanism for change notification so if they don't support either of these options how is the view supposed to know when a property in your viewModel has been changed?
You need your viewModel to use either of these options so that the view can be notified when a property value changes.
This means if a property value is changed in code, the user interface is updated and if a property is changed by user input your viewModel (and ultimately your model) is also updated to reflect these changes. (basically both sides of a binding require a way of communicating a property change to each other).
The INotifyPropertyChanged interface is the preferred method as it means your viewModels are not specific to WPF and can be used by other user interface technologies. also, dependency properties can only be used in types that derive from DependencyObject.
First: You do not need to use INotifyPropertyChanged or DependencyObject at all.
But, and this is the central point in using Binding, there is some Pub / Sub Mechanism in
the Binding, which is listening to those PropertyChanged events and doing the update
of the view in case a relevant property for Binding has changed.
Here is more information on that:
SO on how binding works
Pub Sub aka Publish Subscribe Pattern
INotiyfyPropertyChanged - This property we used in the viewmodel so that if there happens any changes in the UI this property will reflect those changes.
I want to change a DependencyProperty of my ViewModel from a class which connects the application to a database.
This class raises events which should initiate a change of some properties in my ViewModel.
How can I realize that? I don't have the Dispatcher of the View.
I'm assuming you don't really have dependency properties on your viewmodels but rather normal C# properties which raises the PropertyChanged event.
If so, you should be fine already. Modify your properties from your background thread (normal concurrency issues apply obviously) and when they are bound to a WPF element's Dependency Property the runtime system will take care of marshalling the change to the proper thread (by using the view's Dispatcher object)
This works for normal properties, I'm not sure it works for ObservableCollections.
There are also different approaches for doing the marshalling inside the viewmodels. The simplest way is to just store the value of Dispatcher.CurrentDispatcher in your viewmodel's constructor. This works as long as your viewmodels are created on the UI thread.
One immediate solution to the problem is to capture the view's Dispatcher and store it on the view model when you create it, so you can Invoke/BeginInvoke the change to it in response to the event.
That being said, you should consider making your viewmodels use INotifyPropertyChanged with CLR properties rather than DependencyProperties to avoid issues like this. That way, any thread can make changes to your viewmodel and have the results reflected in the view.
I've got a WPF app who's menu is using the commanding capabilities. Everything is wired up just fine and when I click the buttons in the menu, the commands run. However I'm having trouble getting the button's IsEnabled status to respect the CanExecute part of my commands.
One challenge is the commands need to see what you're doing in the UI. For instance, one command should only be available when certain items in a ListBox are selected so I need to get a reference to the ListBox... but since the command is exposed in my view model (MVVM pattern), it doesn't have access to the UI (BTW, the menu is in one user control [parent=mainwindow] while the ListBox is in another user control [parent=mainwindow]).
In addition, even when I hard code the command's CanExecute method to return false, the Enabled property of the button doesn't change... the command won't fire, but it won't change... frustrating. I assume I need to modify/raise the CanExecuteChanged event, but I'm not sure when I should be doing that (can't find a good sample).
Feedback?
Try the Messenger class from MVVMLight. It helps in communicating between ViewModels.
And give this a try:
Have a SelectedItem property in your ListBox's ViewModel. Broadcast messages while the property changes. Register for this message in the menu's ViewModel. Use the SelectedItem property in your CanExecute method for your logic.
Normally, you would bind the Command Property of the MenuItem/Button whatever - that means you still have the CommandParameter to work with - this can then be bound to some other control. However, when the two views do not know each-other, you need som kind of mediator between them (ie. a viewmodel that both views can access - have the listbox SelectedItem/SelectedItems bound to a property two-ways - and let the CommandParameter bind to the same property one-way).
As for when to fire the CanExecuteChanged event - you should fire that whenever there is a change in the logic contained in the CanExecute-method. If it is always false, you should never fire the event, as it will read the initalvalue when the Command-parameter is set. '
If your button is behaving oddly - check to see if the IsEnabled property is influenced by Styles or set directly.
Hope this helps.