This article is a continuation of my “MVVM for Tarded Folks Like Me”. The aim here is not to teach the basics. There’s plenty of information on that out there. Even a tard should be able use the Google. My general intention is to give some guidance on hurdles that any developer who doesn’t have 1500ccs of brain matter might come across while learning how to develop an MVVM application.
I believe bullshit information to be a major hurdle in making well designed MVVM applications. So I wanted to kick this one off with my favorite myth…
Disclaimer: I’m going to speak mostly in the context of Silverlight from here on. Why? I want to talk least common denominator. There’s just so many ways to do things in WPF, I can’t and won’t cover them all. In any case, all concepts here are transferable to WPF. This is also where I get into style and opinion, so it’s going to be quite subjective. It may even piss some people off. Great!
“MVVM is an Overcomplicated Turd”
No, your code is. I can make this counter-claim with a level of certainty. Because I’m a pompous, MVVM-advocating prick? I don’t think I am, but that’s not really for me to say. In my previous article, I break MVVM down to what it is [for WPF/SL] at the core. It’s binding to a class that specifically deals with data for the UI. If that’s too complicated, research it some more. You are of reasonable intelligence. I believe in you.
Where MVVM starts to get complicated, is when you start using other patterns to help out with your MVVM-fu. This is when you feel the need to pass some event or data across the View/ViewModel barrier. It gets “complex” when you want one ViewModel to communicate with another, even though your VMs don’t have direct reference. One accepted practice is to use commanding for your View to talk to your ViewModel. Use a mediator to get your ViewModels to talk in a loosely coupled manner. If you want to see how to use commanding and a mediator, check out Laurent Bugnion’s MVVM Light library. He’s got implementations of both. To better illustrate my point, lets look at how many patterns are supported under Prism. There are at least 13 other patterns NOT MVVM dependant. That’s quite a bit of non-MVVM for what some folks label as an “MVVM Framework”.
There is a great post on Silverlight.net that I recognize as the epitome of MVVM gone bad. It’s MVVM perversion. It’s quite long, so I understand not reading all the way though, so I’ll paraphrase.
JFalcon is not happy and we end up sympathizing with him. We feel bad for his situation. He’s a victim. His architect, who does sound like an MVVM-purist prick, has him developing a numeric spinner control. His requirements were to create a view-model for this control and implement commands to handle the up/down clicks for the spinner.
If that last sentence didn’t raise any flags for you, well don’t worry because it certainly would not have when I started MVVM. “Isn’t this how you do MVVM apps?”, the green-eared, tarded developer might say. HELL NO! Let me explain further…
A View is a Control, a Control is a Control. A Control is Not a View? |or| Yet Another Stupid Programming Analogy
Let’s define what a view is. It’s your “Presentation”, what you “see”, right? Yes! So a Button is something I can see. That’s a view too! No! That’s a control. Before I confuse you (and myself) any more, lets make a real-world analogy. One of those contrived comparisons that fall apart if you look too deep. Maybe something about a car…or a mammal…or…I know!
You’ve all had to sit through a play before, right? Maybe it was Nutcracker or Phantom of the Opera, Lion King on Ice…doesn’t matter. If the answer is “yes”, well I’m sorry, I hate the theater too. But at least you may get where I’m going with this. The point is you have a script, a stage and some actors and props. The actors, they perform on the stage. They perform based off a common script.
Lets bring it back to that analogy I was promising. A view is like a stage. It brings all the actors, or CONTROLS, together. The controls perform based off a script or ViewModel.
Can I have another view within my view, side-by-side with the actors/controls? Yes! But I didn’t want to confuse my theater comparison just yet. But do realize that a view inside a View is ultimately how a non trivial application is composed, but for the concepts I’m dropping, a view should see any contained view as a Control.
Here are some ground rules that I use when deciding if I need a control or a view. I am no authority on any of this, and even though I talk about my rules…I have broken them all in my applications.
You want to make a control (actor) when:
- Anytime you need to use the VSM or animations. I don’t believe you should ever directly use the VSM (ie give your View visual states) or animations in the View. This sounds extreme. I know. I thought so too at first. My reasoning is a View’s purpose in life is to give the controls a place to perform, and provide a script (ViewModel/Data). It should not be concerned with a Visual State [Manager]. You should not have to build extra infrastructure for you VM to tell your View to change states, nor should you be required to have a direct event handler in your code-behind to change states of your View. “But I want to animate my controls on my view. The VSM works so well and it’s not a big deal having some code-behind.” I can’t argue there, and this is not a hard line rule I’m proposing. This is more of a rule I’m suggesting. I handle the “animation” problem with either creating a control, a panel, etc, that handles the animation. Take a look at the TransitioningContentControl. This is a great example of a control that you can style, use the VSM on, include it in your view.
- When the data required for the actor to operate is not domain specific. Think about a . It takes a collection of data. It doesn’t care if the data is a list of monkies. If we need to format our UI based on domain specific data (monkies), create a copy of the control’s style, maybe inside your view, and format away.
- You need to make a wrapper for other controls
- It’s so atomic and simple, you have no choice but to make it a control.
You want to make a View (stage) when:
- You need some controls working in concert and you need a way to delegate domain specific data to them.
- You need to take user input and send it to code for processing against your application’s domain logic.
In summary, I treat the view as a UI mediator (and layout provider, style setter and maybe resource holder) between data and other UI. “Other UI” being controls. Got it?
Getting the Most Out of a Control
I just talked a butt load about controls. I wanted to cover them a little more in detail. One of the things that really changed my XAML life was the concept of lookless controls. It is one of the most powerful parts of WPF/SL, but yet the MOST unused features by folks new to WPF/SL. You create a control that has no XAML associated to it. You define “PARTS”, which are sort of like defining a contract between your lookless control code and it’s style. When a style is applied to your control, you pull reference to the specific elements you want to manipulate in code and/or hook into events on these elements. Generally when creating a lookless control, we create a default generic template. In my practice, this default template is made for the designer of Blend. So they have a literal and visual understanding of what my control is and does. This generic template exists in a special place in your project. Themes\generic.xaml, which is just a ResourceDictionary.
I’m not going to give a tutorial on lookless controls, but I want to give a few short pointers. First, learn how to make these controls from the people who gave you the technology in the first place! Microsoft. They have a lot of their controls open source on codeplex. Look at this real simple one for a numeric spinner control in Silverlight. Notice the attributes on top of the class. Think of this as your code/style contract. The attributes are not needed, but Blend looks for these attributes. So if you want to make life easier in Blend, USE THEM! Next look at the constructor:
public ButtonSpinner() : base()
DefaultStyleKey = typeof(ButtonSpinner);
This tells WPF/SL to look in the Themes\Generic.xaml for a style who's key is of type ButtonSpinner:
The next special part of a lookless control is the OnApplyTemplate override:
public override void OnApplyTemplate()
IncreaseButton = GetTemplateChild(ElementIncreaseButtonName) as ButtonBase;
DecreaseButton = GetTemplateChild(ElementDecreaseButtonName) as ButtonBase;
This override is where we pull out references to controls we are interested in our template. Notice the GetTemplateChild method. Matches the attributes at the top of the class huh? This is part of our code/style contract I was talking about. Here can do whatever we like to the controls we pull from the template. Attach events, directly manipulate. No need for binding or a ViewModel here!
I Hate Diagrams
I mean, I really really fucking hate programming diagrams. In fact, the easiest way for you to get me to zone out is to show me a UML diagram. I may nod at you like I care, but really I’ve totally checked out. This is why I left the diagram for last. Because if you made it this far, you deserve a nap. This image should show most of what I’ve covered so far and how the components communicate. Yes it’s terrible ugly. I’ll try make something more intuitive later.