Silverlight 4: Reliable Commanding with RequerySuggested Functionality? - silverlight

One of the major problems I have been running into in Silverlight is its lack of robust Commanding support (ala WPF). More specifically, I find it very difficult to apply the MVVM pattern cleanly and with reasonable encapsulation because of the requirement to manually call RaiseCanExecuteChanged() on any property that can affect the state of a Command.
As an example, I have a parent/child View bound to a parent/child ViewModel. The parent View binds to a command on the parent ViewModel. The parent view has multiple child views, each of which is a usercontrol that contains a series of built-in controls (textboxes, comboboxes, etc.), which are bound to the child view model.
The state of the parent command (i.e. whether or not it can execute) is based on the state of each of the child controls. For example, all textboxes for all child usercontrols must have valid values. This requires the properties that these controls bind each call RaiseCanExecuteChanged(), which means they have to have knowledge of either the ICommand itself, or a delegate to call the RaiseCanExecuteChanged() method.
Injecting the command or delegate feels wrong to me, especially in situations more complex than described above, for example when there are 3+ layers of controls, and these references need to be passed all the way down the chain. It's also a bit more housekeeping, since each time a child gets instantiated, an extra step of adding the command or delegate has to be taken.
This would all be made much simpler if Silverlight supported CommandManager.RequerySuggested functionality, like WPF does.
I have seen articles that suggested it was possible to implement RequerySuggested in Silverlight (one such article), but see very little commentary on whether it's reliable and performs adequately.
How have others worked around this limitation with Silverlight?

One method I've used in the past is to use the messaging engine from Laurent Bugnion's MVVM Light framework (http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx).
In essence, the children send a message to request that the commands be required. The listener, which can sit in the parent, responds to the messages and calls RaiseCanExecuteChanged().
I've found MVVM Light to be worth it just for the messaging engine. Though you do have to be careful and unregister the listener when the parent view is disposed.
Hope that helps.

Related

Exiting an App or Closing a Control When Using MVVM

In my WPF application, I am using the ViewModelLocator without IoC. I am calling the static ViewModelLocator.Cleanup() method provided by the MVVM-Light framework from my own button which is tied to a "close window command". This Command calls the static ViewModelLocator.Cleanup(), which calls an instance Cleanup() method on my MainWindowViewModel instance. The instance Cleanup() method then sets the property to which the MainWindow binds its DataContext, to null. The setter on the property raises a PropertyChanged event. Curiously, setting this property to null does not cause the window to close.
I am trying to understand why this is the case? If I set the MainWindow's DataContext to null, should that not be the same as Window.Close()? In my case, the Window and all of its elements remain on the screen. However, if I attempt further actions, I get null pointer exceptions, indicating the DataContext binding Property has indeed been set to null; this has also been confirmed in the debugger.
I have created a workaround by hooking the Application.Exit event and issuing a Window.Close() in the event handler in order to create my own "Close Window" button (ie, to create same functionality for my own Button / Command as clicking the X button in the upper right of a Window). Since calling a UI element (ie, the Window instance) from MVVM directly is not MVVM friendly, I used a ViewService to implement the Window.Close() functionality in order to keep the workaround MVVM friendly. I am a big fan of the ViewService idiom (or pattern), but I just don't think it should be necessary here; except, I could see how exiting the app is a special case that perhaps should tie-in with the application lifecycle, and .Net seems to only allow exiting a WPF app by issuing the Window.Close() method.
Thoughts appreciated.
I believe I have found the answer to my original question, in addition to the one raised in my comments discussion with flq.
First, the answer to the original question is that the proper way to close the Window is along the lines of what I did in my described "workaround". Closing an app is a View-initiated process, as it is the Window control that has the bits for how to do it. You can of course hook the Application.Exit event so that you can perform cleanup on your ViewModels, prompt the user to save data, etc..
The question raised by me after some interesting discussion with flq is, if I don't just set a control's DataContext (ie, ViewModel) to null in order to release the View and ViewModel resources, how should I do it?
An interesting discussion with some nuances can be found here, but the basic answer is that you find the parent control and remove the control you want to close from its Children list. Note, this is a different technique with a different goal than just making the control not visible by setting is Visibility property to Collapsed. In the following example, "this" is the control to be removed (ie, "Closed"):
Panel p = (Panel) this.Parent;
p.Children.Remove(this);
I am not sure if you still need to then set the child (ie, "this") to null to re-claim its resources, or, if just removing it from the visual tree will cause WPF to re-claim the resources; the above linked discussion makes no mention. As mentioned in the original discussion, the above technique can be supplemented by hooking it to certain events, or using other application specific logic.

ViewModel-first approach to Silverlight navigation

I am looking for a truly decoupled way of supporting navigation in a Silverlight application using MVVM. I am trying to accomplish more of a "purist" implementation of the pattern where the UI is completely separated from the ViewModels so that the application can actually run entirely without a UI. To do this, I need to support navigation without UI concerns.
I have several ideas how to accomplish this (with Messaging, etc) but haven't come up with a good way of "mapping" the View to the ViewModel so that the UI can show the appropriate View when the ViewModel is "displayed". I recall coming across an article some time ago that described a solution to this very problem but can't seem to locate it online anymore.
Does anyone know how to find this article or have any experience solving this problem?
So here's my somewhat long-winded description what we ended up doing:
First, we decided to use the built-in Page Navigation framework. We had multiple reasons but since it is built-in and is also the navigation framework du jour in Windows 8, we opted to try this approach.
I should also mention that we use MVVM Light and MEF in our applications. (This comes into play below.)
To make this work, we created an application Shell (UserControl) that contains the Frame control. The Shell's DataContext is set to an instance of the ShellViewModel which exposes a single CurrentPage property (of type String). We then bind the Frame's Source property to CurrentPage. This approach is similar to Rachel's app-level ViewModel.
The ShellViewModel registers with the Messenger to receive CurrentPageChanged messages. When the message is received, the CurrentPage property is updated, the PropertyChanged event raised and the UI updated. The message originates from the NavigationService (which implements INavigationService and is injected/imported using MEF).
The NavigationService exposes a NavigateTo method which accepts the string name of the ViewModel representing the destination. This name matches the contract name applied to the ViewModel when exported (using MEF) and used to lookup the instance using our ViewModelLocator.
In the NavigateTo method, we use the ViewModelLocator to retrieve the ViewModel instance, call Deactivate on the current ViewModel (if one), call Activate on the new ViewModel then send the CurrentPageChanged message with the name of the new view as a parameter. Activate/Deactivate are helper methods on the ViewModels that allow us to perform any necessary tasks when the ViewModel is navigated to or from.
This appears to be working well and gives us a very MVVM-ish implementation with all navigation isolated from our ViewModels via the INavigationService and messaging.
The only down-side right now is that while we are using string constants in code to represent the ViewModel names, we are still hard-coding the strings in the Views to set the DataContext. I will be looking into a way to set the DataContext automatically as part of the navigation 'tooling'.
I should mention that this approach was parsed together from a number of sources, including (but not limited to) Rachel and the following links:
http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/01/25/adapting-silverlight-navigation-to-mvvm.aspx
http://blog.galasoft.ch/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx
http://www.geoffhudik.com/tech/2010/10/10/another-wp7-navigation-approach-with-mvvm.html
Usually I have a ViewModel for the entire app, and it contains the CurrentPage and all navigation event handling.
On the View side, I use a ContentControl with it's Content bound to CurrentPage, and use a DataTemplateSelector to determine which View to display for which ViewModel
There's an example here if you're interested, although it uses DataTemplates instead of a DataTemplateSelector.

Using MVVM in WPF, should I launch child windows from View code behind, or ViewModel?

I've been puzzled by this for a while. I am writing quite a large RibbonWindow WPF application using the MVVM pattern. The screen has a RibbonBar menu along the top and the rest of it displays the various Views. Some Views contain other Views and some of these have buttons that launch child Windows.
So far, I have been doing this from the View code behind file, but I'm aware that these files are supposed to be empty when using MVVM. I could move the child window launch code to the ViewModel, but then I would need a reference to the main RibbonWindow (to set as the child window owner) and that doesn't seem right.
Any advice or tips on how this is normally achieved using MVVM would be greatly appreciated.
I usually handle this by creating some sort of WindowViewLoaderService. When your program initializes you register your Window's and your ViewModels with code something like this:
WindowViewLoaderService.Register(TypeOf(MainWindowView), TypeOf(MainWindowViewModel));
WindowViewLoaderService.Register(TypeOf(MyWindowView), TypeOf(MyWindowViewModel));
Then when you can for example call into this service from your ViewModel and all you have to reference is your other ViewModel. For example if you are in your MainWindowViewModel you might have code like this:
var myChildWindowVM = new MyWindowViewModel();
WindowViewLoaderService.ShowWindow(myChildWindowVM);
The WindowViewLoaderService would then look up what View is associated with the specified ViewModel you passed it. It will create that View, Set its DataContext to the ViewModel you passed in, and then display the View.
This way your ViewModels never know about any Views.
You can roll your own one of these services pretty easily. All it needs to do is keep a Dictionary with the key being your ViewModelType and the value being your ViewType. The Register method adds to your dictionary and the ShowWindow method looks up the correct view based on the ViewModel passed in, creates the view, sets the DataContext, and then calls Show on it.
Most MVVM Frameworks provide something like this for you out of the box. For example Caliburn has a slick one that just uses naming convention its called ViewLocator in this Framework. Here is a link that summarizes: http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/04/mvvm-study-segue-introducing-caliburn-micro.aspx
Cinch on the other hand calls it a WPFUIVisualizerService which you can see in action here:
http://www.codeproject.com/KB/WPF/CinchIII.aspx
These should help get you rolling.
Well, one remark to start with is that, "Having no code AT ALL in the code-behind" is actually a "myth". If you want to be pragmatic, and you see that having some code (as little as possible would be better), will make your life easier and solve your problem, then you should go with that.
However, in this situation, there are actually some loosely coupled ways to do this. You could have a service that does the interaction for you. You initiate the interaction with the user from the ViewModel, the service takes care of that (by showing a ChildWindow for example), and gives you back the user's reponse. That service can be mocked for testing easily. And it can be tested seperately.
That is, if you want to do things yourself. If you want a framework to do the heavy lifting for you, you can check out the InteractionRequest functionaity offered by Prism. Here's the MSDN article that talks about adanced MVVM scenarios which includes a section on User Interaction Patterns. That's the way I do it, and it's pretty simple, elegant and straightforward.
Hope this helps :)
To take Matt's answer one step further, you can have all your view's be a user control. Then create a ViewContainer, which is a window with your data templates (as you described).
Then you just ship the viewmodel you wish to open over to the window service, which sets the DataContext. The service would then open the window and the contentcontrol will resolve the correct view for the viewmodel.
This means all the registration is done in the XAML and the window service just knows how to do just that...open and close windows.
This is an old post, but maybe this'll help someone along the way: I use MVVM, and raise events for opening child windows from the ViewModel back to the View. The only code behind is handling the event, opening the window, setting owner of the child window and that's pretty much it. In the viewmodel, if the eventhandler is null, then it's not subscribed to by the view and doesn't fire. The VM does not know about the view. The code is pretty simple also and only takes a few lines.
In this situation View should handle the opening of the child windows.
However, ViewModel might drive the creation of the windows, but calling into View to create a new Windows.
This will save the logic of MVVM pattern: ViewModel has the "brains" but is not involved in a particular window creation.
ViewModel only is used to present system state and UI logic. One viewmodel may be referenced by multiple views. It have no knowledge of UI specific code like parent/child relationship, position, layout, size etc. So it is better to pop child window in view's code-behind with ViewModel's state changed event or command event and event arguments. In this way you can specify which one is the parent view in the UI layer.

Choosing between bound ViewModel properties or messaging to communicate between ViewModel and View using the MVVM Light Toolkit

I'm using MVVM Light toolkit (which I love). I currently have messaging in place for some interaction originating from the ViewModel and intended for consumption by the View. Typically these types of messages indicate the View should do something like hide itself, show a confirmation message that data was saved, etc.
This works. In the constructor for the View, I register with the Messenger:
Messenger.Default.Register<NotificationMessage<PaperNotification>>(this, n => HandlePaperNotification(n));
When I'm using the Messenger to communicate cross-cutting concerns between ViewModels (like identity), I can see that when the ViewModel is cleaned up in the ViewModelLocator, the base class for ViewModels (ViewModelBase) unregisters any subscribed messages. I don't have to do anything, as MVVM Light Toolkit handles that for me. However, when I use them in the Views, I have to expressly unregister them at Closing time, like so:
Messenger.Default.Unregister(this);
I suppose I could implement a base class for Views to inherit from.
However, it strikes me that perhaps this is a code smell to be using the Messenger in the View... it works, but it might not be the best way. I'm wondering if I should instead create a property on the ViewModel and bind whatever part of the View's elements to it. In the example of hiding a form, a property could be a boolean called "Show". As I think about it, I can see that in many cases this will result in having to write a ValueConverter. One way seems less testable. The other way seems to require much more code and perhaps the introduction of excess ValueConverters, which could become a code smell in themselves.
So (after all that build up) my question is this:
Is it preferable to use messages within the View or is it better to add properties (and potentially ValueConverters) to allow the ViewModel to drive it in a more bindable fashion?
In MVVM. ViewModel comunicates with View through DataBinding and Commands. If you need some other functionality, you need to implement it using this means.
Messaging is supposed to be only for ViewModels. Views are supposed to be "stupid" visualisers of your data in ViewModel.
The Messaging logic in MVVM Light is there for communication between ViewModels. I've never run into any communication between View and ViewModel that I couldn't solve with binding and/or commands. Sometimes I need Value Converters and sometimes I need code in the code-behind, but I've never had to make the ViewModel directly push data to the View.
This is an interesting discussion and I found this thread when I was wondering about view model to view communication. Interestingly, MVVMLight's creator seems to find it perfectly acceptable to send messages from a view model to a view. Another example of differing opinions about what is a good MVVM design.

Need advice on implementing UI in WPF

I need some advice on implementing UIs in WPF.
So far, I've been using Code-Behinds, which is extremely easy to get-started, but hell when maintaining/changing/testing.
I've looked at MVP (and its WPF variant - MVVM), but having some trouble getting started.
Assuming I have a UI to build, here's what I think I should do:
1.
Create a "Main UI" Mediator class which specifies ALL high-level operations (LoadSettings(), SetVisibility() ) and events (not triggered by the user, e.g, model data changed) that my UI supports.
2.
Create the "Model" classes to represent the data
3.
Create "ViewModel" classes for my model classes.
4.
For complex behaviours (e.g, a sequence of operations need to be done before the UI can/should update, such as modifying items in a collection), do not rely on ViewModels to update the UI. Instead, do it manually through the Main UI Mediator class.
5.
For simple behaviours (e.g, toggling the visibility/enabled states/etc), use WPF binding to bind the ViewModels' properties directly to the UI.
In this case, the Main UI Mediator class would maintain both the ViewModel and Model objects, and delegate user interactions (to the Model) and UI update requests (to the ViewModel/View) appropriately. The Mediator class also provides a centralised interface which specifies the functionalities of the UI, while acting as a Change Manager (described in GOF's Observer Pattern) to handle complex UI behaviour/reduce redundant UI updates.
Am I on the right track? Should I tweak my approach? Change it completely? At the moment, I lack the experience/knowledge to implement huge/complex UIs, so I don't really know whether I'm on the right track.
Thanks
This is a bit long, sorry about that!
So far, I've been using Code-Behinds, which is extremely easy to get-started, but hell when maintaining/changing/testing.
Yep :) Anytime you have to name a control and write "someControl dot blah" in your code-behind, that's a code smell. It's sometimes unavoidable, but try to limit it as much as possible. Your UI is a projection of the model - ViewModels and ValueConverters are a way to deal with the impedance mismatch between the two domains.
A few problems with your approach:
Create a "Main UI" Mediator class which specifies ALL high-level operations
Instead of doing this, your Window class acts as the "Controller"; the important thing is, use Commanding to define your top-level actions. This way, you can have UserControls decoupled from the Window class, because the UserControl will just call Commands.Open.Execute(null, this), and the Window can handle it, and the UserControl will never explicitly have a dependency on the Window.
Create "ViewModel" classes for my model classes.
In MVVM, the VM part is to help you out - if you can get away with binding directly to the model (i.e. the data doesn't change or you don't mind implementing INotifyPropertyChanged in your models), then doing this (even if you have to use a few IValueConverter classes) is okay. ViewModels are mostly used when the view is so different from the model representation that it'd be ugly to hack up your model, or to "tack on" extra properties that only make sense in this particular view.
while acting as a Change Manager...
Remember that WPF does this for you, via Dependency Properties and INotifyPropertyChanged; don't reinvent the wheel; if you write an OnDataUpdate() function, this is a sign you're not using data binding properly.
e.g, a sequence of operations need to be done before the UI can/should update, such as modifying items in a collection
This is where Commanding is great - your CanExecute function can apply arbitrarily complex logic to decide whether a certain operation can be done, and if you bind it to UI elements like Menus or Buttons, they will automatically disable/enable as needed.
It hasn't been mentioned, but do all of your UI design in XAML.
There is nothing worse than seeing WPF UI's being created via code-behind.

Resources