Need advice on implementing UI in WPF - 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.

Related

How to use MediaElement.NaturalDuration to set MediaTimeline.Duration in WPF MVVM

My MVVM program is a media player and uses the Media Element's Natural Duration property to set the Media Timeline's duration. Before I implemented MVVM design pattern, I could simply put
MyMediaTimeline.Duration = MyMediaElement.NaturalDuration;
in the code-behind. I am new to using MVVM but I believe this is not the correct way to perform this action according to the MVVM design pattern. I believe that MediaElement.NaturalDuration is not a dependency property so it cannot be bound to directly. Do I need to make it a dependency property somehow? Would this be coded in the ViewModel?
When we need to implement functionality like this that relates to UI controls using MVVM, we have a few options. One is to implement some kind of service or manager class that can implement this functionality for us and another is to use Attached Properties. Out of these two options, I believe this second option to be more suitable for this problem.
However, there is absolutely nothing wrong with adding event handlers into the code behind of your view, even when using MVVM. I keep seeing new users panicking over what to do rather than use the code behind when using MVVM. This is a common misconception about MVVM.
If you really know how to use Attached Properties properly, then I would advise that you use one (or more) of those to solve your problem, otherwise I would happily advise you to use the code behind. Note that if your view models are correctly data bound to your views, then you can access your view model from the code behind like this:
TypeOfViewModel viewModel = (TypeOfViewModel)DataContext;

Pattern for using dependency property for non simple type on a WPF user control

I am a newbie to WPF, and am trying to learn the standard idioms. I have a user control that allows the user to enter a mailing address, composed of six text boxes. I have also defined an interface IMailAddress, and a concrete class MailAddress that is a set of properties for the standard mail address fields. (US only for the moment.)
I figure by having an interface it means I could have some database class that holds everything about a person but implements this interface for the specific needs of this control.
What is the idiomatic way to tie this type into the control? I can certainly implement it as a dependency property, but does that make any sense with a type like this? Would I be better making it a standard property, and then raising a routed event when the value changed?
I'm not so much concerned about this specific example, but more generally what is considered best practice for these types of scenario.
Having your user control expose an IMailAddress property as a dependency property is perfectly valid. WPF itself does similar things; for example, ItemsControl expects you to bind a collection to it, so it exposes an ItemsSource dependency property of type IEnumerable.
User controls/custom controls are a good way to represent views, and don't let the MVVM freakazoids tell you otherwise :) Besides, there's no reason this can't work perfectly fine with MVVM - for example:
<local:MailAddressEditor
MailAddress="{Binding Path=Customer.BillingAddress}"
/>
One thing you may like to look at, though, is using a Custom Control instead of a UserControl. This will allow you to build a 'lookless' control that focuses on the logic behind editing an address, and allow users of your control to create Styles independently for rendering the control. When people use your control, they might use:
<local:MailAddressEditor
MailAddress="{Binding Path=Customer.BillingAddress}"
Style="{StaticResource SimpleInlineAddressEditor}"
/>
<local:MailAddressEditor
MailAddress="{Binding Path=Customer.BillingAddress}"
Style="{StaticResource ComplicatedAddressEditorWithGoogleMapsSelector}"
/>
In this case, we have one control, with two styles (and probably two ControlTemplates) to give the fields a different layout.
Custom controls are a great asset to a WPF developer - not everything has to be done via MVVM. Just try to stay conscious of the kind of code going into your custom control - if it's getting a little too logic-y, you might want to move some of that into a view model.
DependencyProperties are sort of fading away as INotifyPropertChanged is taking over with MVVM patterns. You should look at MVVM toolkits if you want to start using proper separation between your interface, data access, and business logic. You can still use DependencyProperties, but I would recommend you build a ViewModel to implement your interactions with your user control. One of the goals of MVVM is making testability easier by providing a ViewModel that can be verifed with unit tests outside of XAML-land.
A great starter MVVM toolkit for WPF is MVVM Light. A heavier weight MVVM toolkit would be Prism.

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.

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.

Multiple "sibling" controls, one-at-a-time visible, MVVM

I've got what I think is a fairly simple problem in Silverlight, and I'd like to solve it using MVVM principles, largely as a way of enhancing my own understanding.
Let's say I have a simple LOB app that's designed to let me load up and edit a single Employee (just an example, for the sake of explanation). In my example, Employee is made up of a number of complex objects - an Employee has a ContactInfo, a Skillset, an EmploymentHistory, an AwardsEarned, etc. The idea is that I can have this app load up a single employee and get access to a number of different editor screens. Each component of an Employee has its own editor screen.
Visually, the app just ha a left-hand nav bar and a main view on the right side. The nav bar just lets me type in an employee number and load it into memory as the "active" employee. It has a simple list of links - clicking a link should load the appropriate editor screen on the right side.
There are a couple concepts that I don't think I understand well enough, and I'm having trouble proceeding. I know there's always more than one way to skin a cat, especially when it comes to WPF/Silverlight/XAML/MVVM, but I'm having trouble thinking through all the different concepts and their repurcussions.
View-First or ViewModel First
After much thinking about MVVM, what seems most natural to me is the concept of viewmodel composition that Josh Smith seems to promote in his often-quoted article. It seems like the idea here is that you literally model your UI by composing viewmodels together, and then you let the viewmodels render themselves via typed DataTemplates. This feels like a very good separation of concerns to me, and it also makes viewmodel communication very direct and easy to understand.
Of course, Silverlight doesn't have the DataType property on DataTemplates, to many complaints: one, two. Regardless, what I see promoted much more often than viewmodel composition is a more view-first design, where the viewmodel for the view is typically instantiated in the view's XAML or via a DI container, meaning that you can't hand it any parameters. I'm having a really hard time understanding this: how is a ViewModel supposed to serve a Model to a View if I never get to tell it what data is in the model? Reaching through a view to get to its viewmodel doesn't seem to make sense either. I'm very hazy in this area but it seems the accepted answer "use a mediator/lightweight messaging framework." I'm just going through some tutorials now on the messaging system in MVVMLight and I'll be looking at similar stuff, if for nothing else than simply to understand the concepts, but if anyone can shed some light on this I'd very much appreciate it. Anything involving Unity/Prism or MEF is valid, but I haven't gotten that far in my quest for knowledge yet :-)
Instantiating Views and Selecting Them
Theoretically (I say that because SL doesn't support DataTemplate DataType), the viewmodel composition approach could make this very simple. I could have the right side of the screen be a content control whose Content property is bound to a property called ActiveEditor. A parameterized command for the hyperlinks would set ActiveEditor to a given viewmodel.
With a more view-first approach, how would I proceed with this? The first thing that comes to mind is instantiating all of the controls in the XAML of the main view.
Is manipulating the Content property of a ContentControl a good way to go for this kind of situation, or am I better off doing something like setting visibility on each individual control?
The ViewModel (VM) is written so that it is 'wired up' to the Model but has no knowledge at all of the View - in fact, this is what makes it very good to unit test (see NUnit) as it has no idea, and less does it care, whether it is being used by a UI or a Test Framework.
The VM exposes public CLR properties which implement the ICommand interface, the View, having instantiated a VM using (generally speaking anyway) its default constructor, then binds its Buttons/Hyperlinks etc to these Command properties like. So, for example, you may have a VM that exposes a CloseCommand to exit the app, the View may contain a MenuItem that binds to that command, such as:
<MenuItem Header="E_xit" Command="{Binding Path=CloseCommand}" />
Now, the VM would also expose a public ObservableCollection of objects that you want to display in your UI. Whether you populate this ObservableCollection as part of the VM constructor, or whether you do it via a UI interaction (say another Command assigned to a Button click) is up to you but the end result is that you bind a View control to this exposed ObservableCollection in XAML like:
<y:DataGrid ItemsSource="{Binding Breakdown}"/>
or equivelant for whatever control you are using to display the data (not sure off the top of my head what elements a DataGrid has in Silverlight as opposed to WPF).
Meanwhile...: The Mediator pattern is used for VM's to interact with each other, not for the View to interact with the VM. For example, you might have a custom TreeView that has its own VM on the same View as the main chart screen. In this case you could use a Mediator for the TreeView's VM to communicate with the Charts VM.
As for the last bit of your question, I think set up a basic framework using Josh Smith way in the article you mentioned and use that method to add additional ViewModels to the right hand side of your silverlight app.
Hope that helps a bit at least.

Resources