Is Dependency Injection possible with a WPF application? - wpf

I want to start using dependency injection in my WPF application, largely for better unit testability. My app is mostly constructed along the M-V-VM pattern.
I'm looking at Autofac for my IoC container, but I don't think that matters too much for this discussion.
Injecting a service into the start window seems straightforward, as I can create the container and resolve from it in App.xaml.cs.
What I'm struggling with is how I can DI ViewModels and Services into User Controls? The user controls are instantiated via XAML markup, so there's no opportunity to Resolve() them.
The best I can think of is to place the container in a Singleton, and have the user controls resolve their ViewModels from the global container. This feels like a half-way solution, at best, as it still required my components to have a dependency on a ServiceLocator.
Is full IoC possible with WPF?
[edit] - Prism has been suggested, but even evaluating Prism seems like a big investment. I'm hoping for something smaller.
[edit] here's a code fragment where I'm stopped
//setup IoC container (in app.xaml.cs)
var builder = new ContainerBuilder();
builder.Register<NewsSource>().As<INewsSource>();
builder.Register<AViewModel>().FactoryScoped();
var container = builder.Build();
// in user control ctor -
// this doesn't work, where do I get the container from
VM = container.Resolve<AViewModel>();
// in app.xaml.cs
// this compiles, but I can't use this uc,
//as the one I want in created via xaml in the primary window
SomeUserControl uc = new SomeUserControl();
uc.VM = container.Resolve<AViewModel>();

It's actually very easy to do. We have examples of this in Prism as jedidja mentioned. You can either have the ViewModel get injected with the View or the View get injected with the ViewModel. In the Prism StockTraderRI, you will see that we inject the View into the ViewModel. Essentially, what happens is that the View (and View interface) has a Model property. That property is implemented in the code-behind to set the DataContext to the value, for example: this.DataContext = value;. In the constructor of the ViewModel, the View gets injected. It then sets View.Model = this; which will pass itself as the DataContext.
You can also easily do the reverse and have the ViewModel injected into the View. I actually prefer this because it means that the ViewModel no longer has any back reference to the view at all. This means when unit-testing the ViewModel, you don't have a view to even Mock. Additionally, it makes the code cleaner, in that in the constructor of the View, it simply sets the DataContext to the ViewModel that was injected.
I talk a bit more about this in the video recording of the Separated Presentation Patterns talk that Jeremy Miller and I gave at Kaizenconf. The first part of which can be found here https://vimeo.com/2189854.

I think you've hit on the issue. The controls need to be injected into their parent rather than created declaratively through XAML.
For DI to work, a DI container should create the class that is accepting dependencies. This means that the parent will not have any instances of the child controls at design time and look something like a shell in the designer. This is probably the recommended approach.
The other "alternative" is to have a global static container called from the control's constructor, or something similar. There is a common pattern in which two constructors are declared, one with a parameter list for constructor injection and the other without parameters that delegates:
// For WPF
public Foo() : this(Global.Container.Resolve<IBar>()) {}
// For the rest of the world
public Foo(IBar bar) { .. }
I would almost call this an antipattern but for the fact that some frameworks leave no other choice.
I'm not even half an expert in WPF, so I'm expecting a healthy serving of downmod here :) but hope this helps. The Autofac group (linked from the homepage) might be another place to ask this question. The Prism or MEF sample apps (which include some WPF examples) should give you an idea of what is possible.

We are experiencing a similar issue. We are looking forward for a solution that will provide Design time support under Expression Blend 2.0 (Strong Type). Plus we are looking forward for a solution to have some Mock+Auto-Generated data sample available under Expression Blend.
Of course, we are looking also to have all those thing work using an IOC pattern.
Paul Stovell as an interesting article to start with:
http://www.paulstovell.com/blog/wpf-dependency-injection-in-xaml
So I try a couple thing to add more valuable design time support for Binding and mocking object at Design time, right now I’m having most of my problem related to get a strong typed connection made between the View (code) to the ModelView(Xaml), I tried a couple scenario:
Solution 1 : Using Generic to create the View
public class MyDotNetcomponent<T> : SomeDotNetcomponent
{
// Inversion of Control Loader…
// Next step add the Inversion of control manager plus
// some MockObject feature to work under design time
public T View {Get;}
}
This solution does not work since Blend does not support Generic inside is design surface but Xaml do have some, well work at runtime but not at design;
Solution 2: ObjectDataProvider
<ObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
<!-- Work in Blend -->
<!—- IOC Issue: we need to use a concrete type and/or static Method there no way to achive a load on demande feature in a easy way -->
Solution 3: Inherit ObjectDataProvider
<CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
<!-- Cannot inherit from ObjectDataProvider to achive the right behavior everything is private-->
Solution 4: Create a mock ObjectDataProvider from scratch to the job
<CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView }" />
<!-- Not working in Blend, quite obvious-->
Solution 5: Create a Markup Extension (Paul Stovell)
<CWM:ServiceMarkup MetaView="{x:Type CP:IFooView}"/>
<!-- Not working in Blend -->
Just to clear one point. When I said “not working in blend”, I mean that the Binding dialog is not usable and the designer needs to handwrite the XAML by itself.
Our next step will probably be to take the time to evaluate the ability to create a plug-in for Expression Blend.

Yes, we do it all the time. You can "inject" your ViewModel into the DataContext of the control.
I actually find WPF being even easier to use with DI. Even the dependency objects and properties work with it seamlessly.

You should take a look at Caliburn - it's a simple WPF/Silverlight MVC framework with support for full DI. It looks really cool and it lets you use any IoC container you want. There are a couple of examples on the documentation wiki

Glen Block (see above) mentions that a common approach is to design your MVVM solution to use the DataContext as the place where you can "resolve" your View Model in the View. Then you can use design extensions from expression blend 2008 (note that you don't need to be using the expression blend design tools to take advantage of this). For example:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MyViewModelMock, IsDesignTimeCreatable=True}"
In your view you can have a property getter that casts your DataContext to the type that you expect (just to make it easier to consume in the code-behind).
private IMyViewModel ViewModel { get { return (IMyViewModel) DataContext; } }
Don't forget to use an interface so that your views are easier to test, or to help you inject different runtime implementations.
In general, you should not be resolving things from the container all over the place in your solution. It is actually considered bad practice to pass your container around in every constructor, or to make it globally accessible. (You should look up discussions of why "Service Locator" strategies constitute an "Anti-Pattern").
Create a public View constructor with explicit dependencies that the container (e.g. Prism Unity or MEF) can resolve.
If necessary, you could also create an internal default constructor to create a mock of your view model (or a real one for that matter). This protects against inadvertent use of this "design constructor" externally (in your "Shell" or wherever). Your test projects can also use such constructors using the "InternalsVisibleToAttribute" in "AssemblyInfo". But of course, that usually isn't necessary since you can inject your mocks using the full dependency constructors anyway, and because the majority of your tests should be focusing on the ViewModel in the first place. Any code in the View should ideally be quite trivial. (If your View requires a lot of testing, then you might want to ask yourself why!)
Glen also mentions that you can inject Views into View Models, or View Models into Views. I much prefer the latter because there are perfectly good techniques for decoupling everything (use of Declarative Binding, Commanding, Event Aggregation, Mediator patterns, etc.). The View Model is where all the heavy lifting will be done to orchestrate core business logic. If all of the necessary "binding" points are provided by the View Model, it really shouldn't need to know ANYTHING about the View (which can mostly be wired up to it declaratively in the XAML).
If we make the View Model agnostic to the source of user-interaction, that makes it much easier to test (preferably first). And it also means that you can easily plug in ANY view (WPF, Silverlight, ASP.NET, Console, etc.). In fact, to ensure that appropriate decoupling has been achieved, we can ask ourselves if a "MVM" (Model-ViewModel) architecture could work in the context of, say, a Workflow service. When you stop to think about it, most of your unit tests will probably be designed on that premise.

I think You have to Decide on View First or Viewmodel First then as given the other answer it Can be decide.. There are several open source framework does it same . I use Caliburn where ViewModel first is taken and its really good approach

I wrote an very light framework where a ViewModel is resolved at runtime by using a IoC (Unity) as a markup extension.
The framework allows for writing XAML without a code behind but still lets you have routed commands, data binding, and event handlers.
In any case, I don't think you need the loose XAML in your case, but if you look at the code (http://xtrememvvm.codeplex.com), it might turn out that you can use some of the code to solve your own issues with injecting View Models and Services.

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;

MVVM, The best way to structure the View

I have made a root AppView, a root AppViewModel for my application as a container for all the things. Within the application view, I have a TabControl that each tab has its own task to do. One tab for imoprting data, one tab for issuing, one tab for management and etc:
App_View[Model] // root
{
TabTask1_View[Model], TabTask2_View[Model], TabTask3_View[Model] // tab items
}
1) In MVVM, Is it standard that I have grouped my whole views and view-models into the main application-view and application-model-view ?
2) In MVVM, The model should be implemented for every view & vm ? Or is it standard if I implement the whole models into one or two class files and share the model between them? I personally think that model part is not specific to a certain view, like the class 'student' that can be used anywhere in the code and is not restricted to a certain view. Based on this, if the models are general and shared, yet, is it good to follow the naming convention Class + 'Model' for it? like StudentModel? Is it helpful/necessary to add 'Model' after the general or shared class name like the thing I said?
3) In WPF, What is the best way to implement the Views? I want to edit and design very easily and without any restriction, and it should be standard enough to cover future needs. There are 4 things to use: Window, Page, UserControl and DataTemplate. Which one is the best option that you go for? UserControl or Page?
4) In WPF, How can I load the UserControl/Page(View) inside a tabItem dynamically at run-time based on the MVVM approach?
You're cheating. That's 4 questions!
1)
In terms of how you group your Views and Viewmodels I've seen people put views and viewmodels in the same namespace/folder and others separate them out into different folders based on functionality. The best option for you is what suits you/your team. There is no "right" way.
2)
Keep it DRY - so don't repeat yourself. It is perfectly sensible to reuse code. If you have common classes keep them common. As for naming, the name of the class should be helpful in explaining what it does: I'm sure you'd be able to figure out what the classes NavigationService, NavigationMenuItem and NavigationMenuView did and probably could put together a good mental model of how they relate. So - if naming a class BlahViewModel or BlahModel is useful to you, do it.
3) Implementing views:
A Window is always shown independently. Pages are intended for use in Navigation applications (usually with Back and Forward buttons, e.g. Internet Explorer). Pages must be hosted in a NavigationWindow or a Frame. If you're looking at dynamically adding/removing content, adding content to ItemsControls (TabControl, etc) then you'll want to be creating user controls. You can put user controls in Page and Window object, into other controls, etc, and are really the workhorse for WPF developers.
4)
You have a number of options here:
1)The quick and dirty way is to create DataTemplate which, on being given a ViewModel of type X, load up and apply the ViewModel to their data context. This will allow you to inject a ViewModel directly into a control and have the correct View render.
An example:
View.xaml
<ContentControl Content="{Binding Error, Mode=OneWay}" />
ViewModel:
private void ReceiveError(ErrorViewModel errorModel)
{
//if (errorModel.AcceptCommand==null || errorModel.AcceptCommand is NoOpCommand)
errorModel.AcceptCommand = new DelegateCommand(ClearError);
Error = errorModel;
}
public ErrorViewModel Error
{
get { return _error; }
set
{
_error = value;
_propertyChangedHelper.NotifyPropertyChanged(this, () => Error);
}
}
Styles.Xaml (ResourceDictionary)
<DataTemplate DataType="{x:Type vm:ErrorViewModel}">
<DataTemplate.Resources>
<conv:CustomisableBooleanToVisibilityConverter x:Key="VisibilityConverter" TrueValue="Visible" FalseValue="Collapsed" />
</DataTemplate.Resources>
<Popup AllowsTransparency="True" PopupAnimation="Fade" Placement="Center" StaysOpen="True"
PlacementTarget="{Binding Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type v:ModuleView}}}"
IsOpen="True" Width="400" SnapsToDevicePixels="True"/>
So you can see I'm injecting my viewmodel directly into the content control and it's using the data template that is bound to the viewmodel's type to find a View for it.
2)
A better bet is to use a DataTemplateSelector. This basically allows you to specify which templates are available for a control and then uses logic you code to determine which datatemplate to use. You can find an example of this here.
3)
Use a framework that abstracts the UI controls away. Microsoft has a framework (free) that does this called Prism. Basically, instead of adding your usercontrols directly to a TabControl,ItemsControl, etc you add your control to a named "Region". This region is mapped to an underlying control and an adaptor is put in place to manage how that UserContorl is added/removed when you ask it to be. You can find an in-depth discussion of this here. Beware, though, Prism is an application framework so implementing this isn't 3 hours work.
Here is not an answer, it's my experience that i'll explain to you and how I handle with MVVM. I started with WPF 3 month ago and I handle with it.
For each new theme/menue/option I create a new project file wich contains the ViewModels and the Views. All Business classes are collected in one Project file because I may have to use it in more than one ViewModel.
Yes, it was helpful for me as beginner to name the the classes ...ViewModel and ..View. It maked it easy for me to separate the diffrences and also it was/is easier to explain other people your classes ( for example if u have a problem with your coding )
I am using UserControls for our different views and I load them into ContentControls and TabControls without any problems.
Have a look at Prism for MVVM-pattern.
Point 1:
It depends. There are two widely used approaches AFAIK. First is as you've said group all VM's that constitute the same Window with direct dependencies to form a class structure that shows your actual program structure. Second is where you use an EventAggregator(Prism) / Messenger(MVVM Light) to loosely link the VM's instead of direct dependency.
Now both approaches have their benefit's
With the first one It's pretty easy to identify your program structure cos your VM dependencies show it clearly, which is not so clearly visible from the second approach.
Second approach helps you a lot when unit testing VM's cos you are not forced to either mock / work-around all the dependent VM's, It also helps code re-factoring a bit when changing project structure(think of "Plug in" classes)
oh and these ^^ are by no means exclusive. You can mix these together well and fine.
Point 2:
Models do not have any recommended 1 <-> 1 relation with a View / VM like what Views have with VM. Models just hold your Business Logic. I've had apps that sometimes do not hold a Model at all. Something there is just 1 Model used by the entire Application(when the back-end is say a c++ library and you just interface with it with a C++/CLI Module). yes maintain the naming convention to append Model class names with "Model"
Point 3
How about all of them? use them where applicable. Do not take a partial preference to any. When a View composes multiple other sections that are by themselves a View with VM I'd have a DataTemplate with the Data a UserControl. Your app almost always uses a Window and Page is useful for navigation based apps I think. Think Page's are what I've used least tbh.
Point 4
This is a question of tutorial's. Take a bunch of examples, see how it's implemented, reason it and pick your approach. If your using VS2010 get MVVM In the box (It's great. no 2 ways about that. Really hope this could get to be updated for VS2012 if it's not already). For VS2012 check out Two Views MVVM CodeProject which shows the concept, you can then apply it to any ItemsControl of your choosing.
Finally atleast when you're starting up, PLEASE start off with using a MVVM helper library. I prefer MVVM Light <- that link has a couple videos by the author of the library showing some usages and you can find extensive help here on SO about it. If you want to do things yourself, learn the basics from it and then implement it yourself. if you take the high road from day-one it's just a much longer learning curve(Just my opinion)

Is there a better way than handling CommandBindings in code behind?

I have an application using MVVM. I'm trying to Intercept key presses on an MCE Remote control for Play, Pause, Stop etc....
Currently I'm using command bindings with a method in the code behind performing the related action on a media element as such
<Window.CommandBindings>
<CommandBinding Command="MediaCommands.Play" Executed="PlayMediaElement"/>
<CommandBinding Command="MediaCommands.Stop" Executed="StopMediaElement"/>
</Window.CommandBindings>
Before trying to include the remote control functionality I had approx 10 view-models/views with nothing in code behind.
I'm wondering if there is a better way to do this so I retain the MVVM pattern or is it perfectly acceptable/preferable to implement in this way.
EDIT - I've moved the Command Bindings from a UserControl inside a View into my MainWindow.xaml and placed the methods into MainWindow.xaml.cs. MainWindow doesn't have a view/viewmodel relationship, simply a content control with a ViewModel linked to it.
In my code behind methods I'm making use of a Mediator to send messages (Play,Pause,Stop etc...) to my mediaplayerviewmodel which in turn interacts with it's respective view. Is this a good idea or is there a better way?
I think Josh Smith created a huge confusion in his 2009 article, when he made a point that his code-behind CS files remained mostly empty. MVVM is not about not having code-behind. It is about separation of concerns. If there is any practical rule you should follow, is to make the ViewModel view agnostic (i.e. no reference from the ViewModel to the View. Think having a second unit test implementation of a 'View' for your ViewModel).
This "no code behind" confusion caused very odd structures just to work arround a problem that shouldn't have existed to begin with.
Having code behind in the MainWindow.xaml.cs is perfectly reasonable solution, as long as you don't have logic there, but simply forward the call to an appropriate method in the View Model. If that was my code I would have created custom commands (a la DelegateCommand from the same article) that binds directly to commands in the ViewModel, but your design is 100% legit as well.
Head over to Codeplex.com and look for Caliburn (or better Caliburn Micro). It extends WPF to actually allow calling of methods with arbitrary parameters pulled from other objects and the method being in the view model / controller without having a "hook method" in code behind just fowwarding the call.
The extensions can do wonderfull thignsl ike pull the value of a textbox and pass it as parameter to a method, then react on the return value - much like a view should.
You run in a limitation of "stock" wpf - which simply can only point towards method handlers in code behind without any regards to parameters. Alterantives exist, even from microsoft.

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.

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