WPF, MVVM, Shell and UserControls - wpf

I am building a WPF app that is based on the MVVM pattern (using MVVM Light). It has an outer "shell" to it that gives the main look to the app (status bar, etc.) and then all the content is contained in various user controls that I swap out with the Telerik RadTransitionControl. My two questions related to this are as follows:
I am building my ViewModels using the ViewModelLocator part for Blendability purposes. This involves a basic static class that returns a new instance of a ViewModel for binding and instances are essentially shared as long as the app is running. The question for this is whether I should use a concept such as a "ViewLocator" in that it is a static class that has a static property for all of my views (the app has ~10 so it's not huge) and when I need to transition to a new view I just pull from the static set. The pros of this are ease of use, but are there cons? Is there a better way to pursue this?
What is the best way to transition views? Currently I am passing an enum to my shell view (via messaging) to indicate which view I need, but this seems really hacky and doesn't support passing certain views arguments. I toyed with a custom class, but I would almost need a different one for every view and it seemed like it might be overkill. What is the standard practice executed by WPF devs for this process?
Thanks in advance for the help. I'm fairly new to WPF so I want to make sure I learn the industry standards and avoid hacks wherever possible.

I work on an application that uses the same pattern. We have a static locator and reference the same ViewModel every time we switch to a different part of the application (details view, list view, map view, etc.) We have had a lot of success with the ViewModelLocator pattern - it is pretty easy to understand. We have not done significant testing with running the application for multiple hours.
We use a TabControl with the tab styling removed to transition between the main screens of the application. This gives us one point of entry (the selected index property that we bind on the "naked" Tabcontrol) to change the major screens of the application. For now, we do not use animations.

Related

How to architect graphically-intensive Silverlight app using MVVM?

I'd like to create a Silverlight app using WCF Ria Services and the MVVM design pattern.
The main page of the app will consist of a "shell" and a large number (10s or 100s) of objects of different look (shape/size/properties) linked to each other (forming a sort of graph).
These items need to be mouse-draggable and their current position/state needs to be saved to the back-end database.
I feel that the best way to achieve this would be to have a small ViewModel and View for each item displayed, put all the important properties into the ViewModel and then somehow display all these Views in the main "shell".
However, I don't know how exactly this could be achieved. I considered using MVVM Light, but didn't find any example that would show something similar.
Can anybody point me to some examples or ideas about how this could be done?
"When all you have is a hammer, everything looks like a nail" :)
MVVM is not designed to manage graphic intensive situation like the one you describe. It is a glue for stitching together high-level concepts in a flexible manner. With MVVM you are adding overheads that will impact performance (e.g. binding uses reflection behind the scenes). The more objects involved, the greater the impact.
The best starting point I can suggest is to imagine what you need from a 3rd party control (e.g. a custom control/container) and, if one does not actually exist already, build it as if it were a third party custom control.
You will find in practice that custom controls are seldom based on MVVM, for performance reasons if not just because "they often don't need it". They may well expose MVVM compatible properties for the external interface, but not for the low-level internals.
MVVM is a relatively high-level technique. Do not feel you have to implement it on everything.
Following MVVM do the next:
Model - create model object which will be responsible for fetching and persistence coordinates of the shapes on the screen;
View Model - one view model which will initiate fetching and persistance model objects;
View - in your case, it's a place where you do most of your work. Create custom control based on ItemsControl with Canvas panel. Custom control should pass collection of the model objects in ItemsSource, allow to drag and drop containers and call the view model command when user drops container in some place
Have a look at the Telerik controls, specifically radTileView, this seems to have the functionality that your looking for. They also have a persistance framework that should allow you to save the position of the tiles back to you database.

View and ViewModel getting too large

While adding extra functionality to the main view I have in my application, I've realized that the amount of code will soon become a problem (currently around 600 lines of code in my viewmodel and I still have plenty to add).
I've been looking around for articles on how to split/design your view into smaller components, but I haven't found a satisfying solution. One person suggested using child viewmodels but that presented with other problems (dependency between the viewmodels).
I've thought of using user controls, but there is nothing on the View that I use on other Views so it kind of defeats the purpose of user controls.
What is a correct approach in this situation?
Thanks,
Adrian
If you want to split a view into component parts, then you need to do view composition. If you are building an MVVM app, then you should really be using an MVVM framework. Something like Caliburn.Micro makes view composition incredibly easy.
There doesn't necessarily have to be dependencies between the view models, they should only know about what they need in order to produce their view. This could be a subset of the business object that the parent view model contains. As the parent view model will have references to all of the child view models, it can pass the relevant parts of the business object to them at the point of their construction.
I would agree with using Caliburn Micro.
However, to play devil's advocate you could split out your ViewModel File into separate files (same class name) and use the partial keyword before the class keyword. Its generally tidier and one step-away (non-breaking precursor) from breaking-up into separate classes.
I also agree Caliburn.Micro is a good solution for splitting your application in smaller components.
In Caliburn.Micro the communication between viewmodels is based on the Event aggregator pattern.
This makes a loose coupling between viewmodels
Splitting up is not ideal.
It looks as if the Caliburn toolkit focuses on events, whereas my application largely relies on ICommand implementations.
To me, the first encounter with Caliburn.Micro has been unsatisfactory.
The setup appeared to be tailored to VS2010 - which sounded promissing to me - because I do have VS2010 pro. But I got lost in the setup's of Silverlight.
Compared to toolkits like Prism it lacks the ease of an start.
It just takes to much time to switch now.
I use my own MVVM paradigm, it is less abstract than the Caliburn, it integrates multilanguage support everywhere, and it just faces one acceptable problem of some sources getting too big because of the nature of the Binding/DataContext paradigm.
For this problem I accept that "partial class" is a solution - even though I know there is a more elegant solution available.
In the heat of my work, I cannot change to another toolkit.
So I gently wait for Microsoft to allow for more flexibility around that Binding/DataContext paradigm.
It may be the case that Caliburn shows more intelligence allocating a viewmodel to some item. Does it ? (I think it does.)
What might be another option is to define a custom (xaml useable) object that triggers a custom allocator which control is to be allocated to which viewmodel. How about that ?

Lightweight View Models For WPF

I understand MVVM's usefulness in the context of a large team developing a shrink-wrapped application over a long period of time. But in the context of an internal LOB application, MVVM seems overkill and I'm having trouble swallowing the overhead of debugging declaritive databindings, jumping from layer to layer to layer, and extracting VM's that are barely more than the Model with a command or two. Even accepting that overhead, still leaves me with the holes in MVVM like dialogs. A few things I've considered is:
Binding directly to the Model and do old-school event handlers for form interaction
Binding a user control or window to itself, effectively using the code behind as the VM.
Include a property in my VM to reference the related view.
Make ViewModel's subclasses of a View.
The above items and their combinations address some problems but not all. I do realize that I might sacrifice testability. What other technical (not conceptual like SOC) issues will I run into using one or more of these practices?
I always use MVVM when coding in WPF or Silverlight, even for small single-page apps. It makes it much easier to test and maintain in the long run, and I find it faster to create apps with it than without it
I don't mind taking some shortcuts in smaller apps, such as binding to the Model instead of exposing the Model's properties in the ViewModel, or defining my View in a DataTemplate instead of a UserControl, or using Window's Dialogs in my ViewModels, but I would never consider doing a WPF or Silverlight app without MVVM.
If you want, I have an example of a very simple app done with MVVM here
Code re-usability comes to mind. Properly written VM's could be re-used behind Silverlight or WP7 implementations down the road.

How do I switch views in a WPF application using Unity and MVVM?

I am very new to WPF and am trying to set up an application that requires switching of views.
For example, a user is viewing a system that contains a number of components, when they click on a component, it should switch to a view that is associated to that component, replacing the previous system view. It's my understanding a Controller should be used here but the implementation eludes me.
I have found a few examples, but the projects are a bit too large for me to actually follow what is going on specifically with the view switching. What would really help me here is some example code from the Unity setup in the App file that allows multiple views, the Code in the controller that switches the view, and the code associated with a button that makes the controller switch the view.
Thanks
If you are just beginning with WPF and diving directly into using IoC/MVVM, then you may want to consider taking a step back and starting with the WPF fundamentals, i.e., layouts, routed events, commanding, binding, dependency properties, INotifyPropertyChanged, etc...
To get you started: tutorials on wpf and mvvm.
For most of us mere mortals, WPF has a steep learning curve. Yet, once you make it over that first hump, the 'aha moments' start kicking in on a regular basis.
I'm using Mvvm-Light, but I believe Unity will be similar.
You should have a ViewModelLocator where you register ViewModels.
You should have somewhere styles or datatemplates that tell the framework what view to show depending on the view model encountered.
You should have some property you bind to, that is a base view model.
From there, all you'll have to do is change that property to a different view model, and your view will update accordingly.
As Metro said, steep learning curve, but once you get used to it, it starts to make sense :)

Prism: Looking for ideas of how to design apps that don't necessarily comply to a standard region layout

I have an app that has several modules that have completely different functionality and I'm trying to figure out the best way to implement this using prism.
To try and better explain, I'll try to use Northwind as an example. I have 3 modules, orders, customers & employees.
The customer module will allow you to do anything pertaining to a customer. Add, remove and edit. I'm going to use scope regions for the main view in the customer module to handle all the different views I need to show here.
In the scenario above, I only want to load a module when a user wants to work with say a customer, order or employee.
You have these modules laid out and realize that you need to be able to show Orders for customer or sales people which are obviously employees.
What would you do here in this scenario as you wouldn't want to create an entirely new modules for say employeeOrders and customerOrders and you wouldn't want to duplicate any order related code.
I'm starting to wonder if it's feasible to think about building a composite application using prism if you're building an app like Outlook, but for a LOB business app, I've yet to find a good sample of how to do this and not break some of the principles of MVVM and definitions of Prism in order to do so.
I'm just 3 weeks into Prism and still learning but this is the biggest issue I'm running into.
Any thoughts?
You should be using the Event Aggregator for these types of communication scenarios. Essentially, you want a module to provide functionality but also expose events that can be invoked from other modules. You can also register a service in the Unity container. For example:
public interface ICustomerOrderInvoker
{
void DisplayCustomerOrdersInRegion(string customerId, string regionName);
}
These techniques are somewhat orthogonal to MVVM. Your event handler can create a view/viewmodel pair and insert them into a region. Or your event handler can create a UserControl with all functionality implemented in code behind and adds it to a region. The beauty of the composite UI is that your modules can use MVVM and another team's modules can use straight forward user controls or MVP or MVC or anything really; the point is that all the modules are composed into one application regardless of how they are implemented because they use the patterns established in Prism like regions, events, etc.
In your particular case:
You have these modules laid out and realize that you need to be able to show Orders for customer or sales people which are obviously employees.
Your Order module will certainly be aware of the concept of a customer id since the Order entity is associated with a customer. The Order module should expose an CompositePresentationEvent that displays a view that has all the orders for a particular customer id.
The point of Prism is to create logically separate and loosely coupled pieces of functionality. This does not mean that the modules do not communicate with each other, but rather that the communication happens in a limited and loosely coupled manner. You can certainly write LOB applications using this pattern and MVVM; many of us have been for years now. :)
Im working on a similar problem (and am new to Prism too), as yet don't have a solution. I think when using Prism its tempting to use the framework as the reference implementation intends, but it doesn't need to be so.
Prism should (when used correctly) facilitate software development, not hinder it. So don't get too stuck in the idea that any implementation must meet strict decoupled refactorised super patternised standards!
What I am doing/intending to do is create a MainModule, which has in it much of my core functionality, including a MainView/MainViewModel user control. The Shell then has one region "Main" and on MainModule load the MainView is injected into it as per standard prism usage.
I'm using a Docking Manager from Telerik (compatible with Silverlight and WPF) on the MainView and have implemented a class IDockingManager / DockingManager class in Infrastructure which is registered with Unity as a singleton (ContainerControlledLifetimeManager) in the bootstrapper.
Anywhere in my app I can get the IDockingManager instance and inject a view by calling IDockingManager.DockView(IView view, DockingParameters args). The DockingParameters can contain information such as where to dock (Left, right, top, bottom, tabbed document) and also the parent container to dock in.
This is the part I've not got to yet - I can dock left/right/top/bottom on the main view but I want to implement an attached property or something on my child views registering them as a DockSite when docked. So for instance I could dock a Treeview on the left and dock underneath that a listview by using the Treeview name as parent DockSite and DockBottom as the side.
Hope that makes sense, I've rambled without really explaining too well. Basically what Im saying is Im not using regions at all (except to inject the MainView) in this application and have created a class to handle view injection into dockable containers. It's not strictly Prism but Prism is there to make my life easier, not the other way around ;)

Resources