The video links require Microsoft Silverlight 1.0 or later. If you do not have it, you will be prompted to install it when you click one of the links or you can download Silverlight here. Windows XP or Vista required.

Introduction

This article uses the WPF Password Manager, Cipher Text application as fertile ground for exploring the WPF UI Design Pattern, Model-View-ViewModel or MVVM. The application sports many cool features and some WPF goodness.

In this article I'll cover a number of MVVM coding scenarios and techniques along with using Cipher Text.

Background

My first .NET application after graduating from the SetFocus .NET Masters Program in 2003 was a .NET 2.0 Windows Forms password manager. I've been using this same program for securing my passwords for the last five years.

I've been studying and writing WPF Applications using the WPF UI Design Pattern, MVVM. I'm sold that using MVVM for WPF Line of Business (LOB) applications is the way to go.

Now I wanted to see if I could create a fluid and dynamic application using MVVM. Basically, I wanted to take MVVM out for a test drive, push the envelope and see where it took me. The time spent on Cipher Text was time very well spent and I hope you can learn more about MVVM from this article.

This article is about MVVM coding scenarios and techniques as opposed to the application used to surface them. I do hope that you like the application too.

Designer Developer Workflow: as I was writing Cipher Text its UI was plain and simple. After finishing the application, I took it into Microsoft Expression Blend for a makeover. I liked the workflow of completing the application before starting the beautification process.

During application development I made extensive use of my XAML Power Toys Visual Studio Add-In. If you have not yet seen XAML Power Toys, please visit my blog and download it.

Let's cover the Cipher Text application first and then dive into MVVM.

WPF Password Manager, Cipher Text Application

Application Features

Data stored in encrypted file

Flexible password generator

Instant full text search feature

Nine pre-established data entry forms (can be modified at run-time)

Run-time modification of a record's shape and field behavior (add, change and remove fields)

Run-time configurable case correction rules

Dynamic and rich field validation based on assigned field behavior

Single click copy of any data to the clipboard

Nice WPF UI

"How To" usage video for getting the most of Cipher Text

Single file XCOPY deployment

Application Requirements

.NET Framework 3.5 with SP1 applied

Application Introduction

The application stores its data in an encrypted file using symmetric encryption employing Triple Data Encryption Standard algorithm (TripleDES). While this is not an article on the cryptography namespaces in .NET, it does demonstrate the reading and writing of a serialized object graph to an encrypted file.

This application can be used "as is" to store your passwords. However please note two very important items:

Once decrypted, your data is in memory and can be written to the Windows swap file by the operating system. If your computer is then compromised, a hacker could potentially view data in your swap file. (I'm still trying to figure out how to allocated memory in a managed program that does not get written to the Windows swap file, when I do, I'll update the application.)

If you forget your password, your data is lost. There are no hacks, tricks, workarounds or magic fairy dust to open your data file. A brute force dictionary hack is probably the only way to decrypt the file. Please don't lose or forget your password.

Back in 2003 when I wrote the first version the application met my needs. Then a year later, banks and web sites started asking me to assign a security question to my accounts or for me to provide my mother's maidan name. Since my original application didn't have the ability to update the shape of a record without an application recompile, I put the extra information in a notes field. Now my bank asks for three security questions and an icon to view.

After five years of daily application usage I knew what features I wanted to add. So when I set out to write this program, I needed the ability to change the shape of a record at run-time. I needed to be able to add, change or remove fields. I needed to be able to change which fields are required, which fields have case correction applied and which fields are validated against a set of rules. I also wanted to have instant full text searching of all my data.

Application UI

There is a wind blowing through UI Designer spaces that is pushing UI's to be less busy; to clear UI adorners and affordances until the user is actually using them. For example, hiding a ComboBox's familiar down arrow until the user mouses over the ComboBox. I'm not sure I'm on board with all this yet, but decided to open the door and allow a gentle breeze to influence my design.

Login

First Time Use Login

Login

The first time the application is opened the password for the application is created. By design, the first time password is displayed in clear text so the user can view it while typing it. The standard login form masks the password as its being entered.

Getting Started

After logging in the first time, the above application is displayed.

The set of buttons on the left control filtering and permit a new record to be added to the database. The text at the very top is darkened until the user mouses over it. The data viewer on the right allows for full text searching and data viewing.

Category Buttons

Not Selected

Selected

Mouse Over

Only one category can be selected at a time. When selected, only that category's records are displayed. The 'All Records' category displays all records in the database and is selected by default when the application opens.

When the user mouses over the category, the category is no longer dimmed and a green plus icon is display in the button. Clicking the green plus icon displays an empty record that the user can edit and save to the database. (This is an example of hiding a UI element until it is needed or available for use. I think it produces a cleaner UI.)

Filtering

After selecting a category, the title of the data viewer (area in top red box) changes to reflect the current category. The filter TextBox displays a watermark indicating that no filter is currently applied.

Once the user beings entering text the title of the data viewer changes, indicating a filtered list is being displayed. Also a button appears at the end of the filter text box that allows for single click clearing of the filter TextBox.

Edit Record

Each category has a default edit form. The user can customize each edit form on the fly. The red "!" indicates a field needs attention before the data can be saved. If the user mouses over the red "!" a ToolTip appears, explaining the required corrective action.

When the yellow Key Icon is clicked it opens the create password dialog.

The bottom black bar organizes the possible actions for this form. Actions that are not currently permitted are grayed out.

When the form is valid, the Save command will be enabled. (In case you're wondering, that is the real customer support number for Amazon.com.)

Each of the field tags except Date Created and Date Modified are hyperlinks that when clicked, copy the corresponding field to the clipboard. Additionally when the field tags are dragged, a drag and drop operation is initiated. This allows the dragging of data to other applications or copying data to other fields.

After saving the data the record is added to the database and the edit form is closed.

When editing the Amazon record, the URL field was filled in. When a record with a URL is displayed in the data viewer, the title text is white. Notice that the Expression Blend License record title is gray. When a title field is white, this indicates it's a hyperlink that when clicked will take the user to the web site.

Also, when editing the Amazon record, the User Name and Password fields were entered. When a record with a User Name and/or a Password is displayed in the data viewer, the user and/or key icons are displayed. When these icons are clicked the information is copied to the clipboard.

Modify Form

Form modification has two states. First the form can be in a modification state and one or more fields can be in a validation rule modification state. The above image shows the form in a modification state. When the entire form is valid (including data), the form can be returned to a normal form state by clicking the 'Normal Form' hyperlink in the lower left corner. The form can also be saved when it is valid.

The title and notes fields can't be modified.

Field Validation Rule Modification

The above image shows the phone field tag modified to indicate that the phone number is the Customer Support number. The phone fields allow for notes to be added after the phone number, so I could have indicated this number is the customer support by adding this information after the phone number.

When a field is expanded as the above Customer Support field is, if the field is not valid, the green check mark icon will be disabled, preventing the field from being collapsed until the fields are valid.

The second phone field has been marked for delete and will be removed when the form is saved.

The Max Len field sets the maximum length for the text in the data field.

When Is Required is checked, this makes the data field required entry.

The Type determines the role the field plays in the application and how it is validated.

Credit Card Number - validates the credit card number

Email - validates the email

IP Address - validates the IP Address

Password Primary - displays the key icon to the right of the field data, allowing a password to be generated. The Password Primary field is also causes the data viewer to display the key icon.

Password Secondary - displays the key icon to the right of the field data, allowing a password to be generated.

Plain Text - no rule applied or action taken

Routing Number - validates the routing number

URL Primary - validates the URL. The URL Primary field also causes the title field in the data viewer to be displayed in white and become a hyperlink.

URL Secondary - validates the URL

User Name Primary - causes the data viewer to display the user icon

User Name Secondary - no rule applied or action taken

The Case determines how the application modifies entered data in the field.

Lower - changes data case to lower case

None - no changes made to data

Outlook Phone - attempts to format the data like Microsoft Outlook. Also applies Proper case to text after the phone number.

Modifying Casing Rules

Casing rules as very simple. Once the data field has been changed to proper case, the above rules are applied. For example, let's say your data is, "125 110th St Se". You want the address displayed as, "125 110TH St SE". In order words, you want the abbreviation for South East to be displayed in upper case.

The first rule looks for " Se " and replaces it with " SE ". Notice that the white space in the fields. You wouldn't want to replace all occurrences of "Se" with "SE" as this would cause problems.

The Modify Casing Rules form is fully editable. Each row can be changed without placing the form in an edit mode. If you want to remove a casing rule, click the delete button. If you delete a rule and want it back, simply press the Cancel hyperlink, the form will close and no changes written to the database.

The only validation requirement is that the, "Look For" string and "Replace With" string are the same length.

The green plus icon allows adding a new rule.

When all rules are valid, the Save command is enabled. If any rules are not valid (i.e. not the same length) the Save command will be disabled.

Modified Form

The above form has been modified and data entry completed. Extra fields have been removed and the Phone field tag changed to Customer Service.

Top Hyperlink Bar

The top hyperlink bar text is normally gray. When the mouse is moved over it, the text foreground changes to white.

Float On Top - when clicked, floats the application on top of other windows. This is useful when dragging and dropping text from the application to other applications like a web browser.

'How To Video' - is a hyperlink to the instructional video for the application. This video requires Silverlight 1.0 or later to view.

Code Project Article - is a hyperlink to this article

Karl's Blog - is a hyperlink to my blog

Change Password

The Change Password dialog requires the current password be entered and a new password entered before the Save command is enabled. When the Save command is executed, the database is encrypted using the new password.

Category Buttons

Most of you know Karl was not blessed with any design skills. For this application, I wanted to break my usual pattern of Menus, ToolBars, StatusBar, square buttons and attempt to author an application that has some WPF goodness. I spent a good bit of time trying to design a layout that I liked (or thought would not look like chimps throwing feces). I started looking around and found a cool demo for the XCEED WPF products. I used the demo application for inspiration and went to work.

The behavior I wanted from the category buttons was to only allow one button to be selected at a time. This sounds like a job for the RadioButton or ToggleButton. I chose the RadioButton.

One of the most awesome features of WPF is the ability to re-template a control to have the look, feel and behavior you need without requiring the control to be subclassed.

The category button is a multi-layer button with cool features and mouse over effects. The multiple layers allow elements to render behind other opaque layers and show through them. The multiple layers combined with WPF triggers also makes it very easy to dim the button when it's not selected or the mouse is not over it. The layering is achieved by placing UI Elements as children of a Grid in a single row.

I used Microsoft Expression Blend to create the below control template. Blend makes it very easy to draw paths, layer controls, set gradient values and create required triggers. I also like the zoom & pan features of blend that makes it super easy to zoom into view any portion of your scene.

The below CardTypeCommandView UserControl is our category button and is also the DataTemplate for the CardTypeCommandViewModel.

The triggers provide a scale animation when the mouse is moved over or leaves the category button. A trigger also displays the green plus Add icon when the mouse is over the button unless the category is the, "All Records" category. The IsAllRecordsConverter provides the "All Records" testing and set the Visibility is of the Add icon in the above DataTrigger.

All buttons data bind to an ICommand property on the DataContext, in this case the CardTypeCommandViewModel.

Exploring MVVM Coding Scenarios

MVVM is a WPF UI Design pattern; it's a set of guidelines to help solve a problem. I like MVVM because it facilitates application Unit Testing provided for free in Visual Studio 2008 Professional. I'm not a purest by any means. I do what is required to get the work done. Delivering applications that can be Unit Tested and maintained over time is my primary objective and always overrides strict adherence to a pattern or line of thinking. So like my great friend and mentor Josh Smith says, "put away the flame throwers" and let's get into some code.

Rather than walk the reader though the entire application, I thought it best to pick some coding scenarios and see how MVVM can help solve the problem.

For those that are brand new to MVVM, please see the references at the bottom of this article. I will also post an Introduction to MVVM on my blog soon.

RelayCommand

The RelayCommand comes in two flavors, Generic and non-Generic. When using the Generic version, it allows the developer to specify the Type that the Command Parameter is. In the non-Generic version the Command Parameter is Type Object.

The RelayCommand radically reduces the number of command classes an application would require without it by it.

For example, a ViewModel needs to expose four commands to the UI. Your first thought may be to create four unique command objects to handle the requirement. A simpler and much cleaner approach is to expose the commands as read-only properties on the ViewModel of Type ICommand. In the property getter create a RelayCommand to handle the command Execute and command CanExecute methods.

In the above code snippet, the first ICommand property has assigned the Execute delegate to the GeneratePasswordExecute method and the CanExecute delegate to the CanGeneratePasswordExecute method.

Note the naming convention I've adopted. After coding ViewModel's with more than a few commands, appending "Execute" to the Execute command name makes it very easy to locate the method in IntelliSense. For the CanExecute method names, I've pre-pended, "Can" and appended "Execute" for the same reason.

The second ICommand property does not have a CanExecute delegate assigned. This command is enabled all the time. The RelayCommand takes care of returning True when called, which in effects keeps the UI Element that is bound to the ICommand enabled all the time.

In WPF there is a static class, CommandManager that handles the task of automatically enabling and disabling commands. This feature (like many others) comes at a price. When using many RoutedCommands in an application, CommandManager can causes some performance issues because the CommandManager raises the RequerySuggested RoutedEvent a lot. For example, every time a key is pressed this event and its corresponding preview event travels through the WPF Element Tree.

The ICommand pattern here does not use RoutedCommands. When the UI Element executes a command, the RelayCommand delegates are executed directly.

If however you want to take advantage of the CommandManager automatically enabling and disabling your UI Element commands you have to sign up for this service.

The RelayCommand in this article has a modification that makes registering with the CommandManager SuggestedRequery event optional. Note the overloaded constructor in the above RelayCommand class diagram. If the developer does not supply a delegate for the CanExecute method, the RelayCommand does not register for the SuggestedRequery event.

The RelayCommand is very performant. I have a test application with 100 unique buttons with the Command property bound to an ICommand property with a backing RelayCommand with automatic enabling and disabling enabled with no effect on performance.

Tip: You can use the RelayCommand even if you're not using MVVM. The pattern is the same. This coding technique can give you the power and flexibility of WPF commands without the CommandBinings and all the associated overhead.

List of Commands Scenario

The developer has a list of objects and wants to associate one of more actions with each object. The objects need to be rendered as a list in the UI. The objects can be sourced from a database or a static set of application data.

One solution made easy by MVVM is to wrap each object in a ViewModel. Then associate that wrapper ViewModel with a DataTemplate and allow the WPF Resources system to look up the correct DataTemplate for the data object (ViewModel). Wrapping each object in a ViewModel allows the DataTemplate (View) to data bind required commands to the ViewModel and for reshaping of data if required.

The concrete example of this scenario in Cipher Text is the category buttons on the left side of the application.

The driving data for this scenario is the CardTypes collection in the Database object. The CardTypes collection defines each of the application card types by specifying its title, icon and default form fields.

We now use MVVM to reshape the CardType data making it selectable and associating two commands with it.

The below block of code from the ApplicationMainWindowViewModel class. When the CardTypeCommands property is first accessed by the UI, it creates a ReadOnlyCollection of Type CardTypeCommandViewModels. The LoadCardTypeCommands function is passed in the constructor of the ReadOnlyCollection.

The LoadCardTypeCommands function iterates through the DataBase.CardTypes collection, creating one CardTypeCommandViewModel for each CardType. Notice that the RelayCommands are of Type CardType. This makes it clean when the FilterExecute and NewExecute methods are called by assigning a concrete Type for the method parameter instead of Objectthat would require casting.

The RadioButton XAML code snippet shows CardTypeCommandViewModel being consumed by the CardTypeCommandView.

Take note of the GroupName property. By assigning each RadioButton to the same GroupName we get the behavior we are looking for, single selected Category button.

Binding to a Command and passing a Command Parameter in XAML could not be easier.

By binding to the IsChecked to the IsSelected property, the button can be selected in code on the UI.

Doesn't this just feel natural? Model exposed by a ViewModel to a View. ViewModel adapting Model to the View. View responding to data changes in the ViewModel. ViewModel responding to data changes from the Model and View.

List of Commands Scenario Note

Normally when a ViewModel exposes an ICommand property, it also handles the Execute and CanExecute delegates.

In the above scenario, the NewExecute and FilterExecute methods are members of the ApplicationMainWindowViewModel class. The ApplicationMainWindowViewModel class handles the adding and filtering operations for the application so it makes sense to want this class to handle command Execute methods.

If we didn't use this technique, the CardTypeCommandViewModel would either have to raise an event when a command was executed or have knowledge of the ApplicationMainWindowViewModel and call methods on it.

The ListView's ItemsSource is a ReadOnlyCollection(Of CardTypeCommandViewModel). When WPF renders the ListView Content, it looks up the DataTempate for the CardTypeCommandViewModel and finds it in the above DataTemplate. The CardTypeCommandView is the cool button we described earlier.

Getting the buttons to stagger within the ListView took some thought. I was going to write my own panel to lay the buttons out. Then I remembered the new AlternationCount property and wrote the above alternatingListViewItemStyle Style. By simply adjusting the margins of the buttons in the Trigger, I got the effect I wanted without having to author a panel control.

Showing and Hiding Views and Focus Setting Scenario

The developer wants to display an edit form in response to a command. When the edit form is brought into view, Keyboard Focus needs to be set to the first UI Control on the form.

We could display the form in another window; could add the form to a TabControl or we could layer the window on top of other UI Elements in the application.

The concrete example of this scenario in Cipher Text is the record edit form that is displayed when the user double clicks a record in the data viewer.

<UserControlx:Class="DataEditorView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:CipherText"TargetUpdated="VisibilityChanged_EventHandler"Visibility="{Binding
Path=DataEditorVisibility,
NotifyOnTargetUpdated=True,
FallbackValue={x:Static Visibility.Hidden}}"><!--<span class="code-comment">
The FallbackValue must be Hidden. If it's Collapsed
the DataBindings don't set up correctly initially.
After this DataEditorView has been used once, it can
either be Collapsed or Hidden.
--></span>

To accomplish the simple task of showing and hiding a View we will be using data binding (big surprise right). Again we see the simplicity of MVVM in action. A View responding to data changes in the ViewModel.

The top snippet has two Views in the same Grid Row. The bottom View DataEditorView will be rendered on top of DatabaseView if it is visible. The DataEditorView is initially hidden so the DatabaseView will be in view in the UI.

When the DataEditorView.DataContext Is Nothing (nulll), the above Visibility property would assume its FallbackValue of Hidden because the binding returned Nothing (null).

The only thing left is to set focus to the first field in the View when the View is displayed. Here we assign the TargetUpdate event handler to below VisibilityChanged_EventHandler. This event will be raised each time the Visibility property is changed.

This event handler gives Keyboard Focus to the Title TextBox each time the View's Visibility changes to Visible.

'HACK - Setting Focus To a View field
'When the View is brought into View, this event handler is called
' by the DataEditorView.Visibility binding and the TargetUpdated attached event
PrivateSub VisibilityChanged_EventHandler( _
ByVal sender As System.Object, _
ByVal e As System.Windows.Data.DataTransferEventArgs)
e.Handled = TrueIfMe.Visibility = Windows.Visibility.Visible Then
Keyboard.Focus(Me.txtTitle)
EndIfEndSub

Oh NO! You have code in the View code behind. Yes I do and it's all good. MVVM like most design patterns is a set of guidelines, not hard and fast rules. Design patterns when followed keep you out of trouble and prevent you from reinventing the wheel so they are a good thing.

Josh and I spoke about this a good bit when we wrote the Creating an Internationalized Wizard in WPF application. If the code is UI specific and does not require Unit Testing then having the code in the code behind is fine. Have a look at the code behind files, you'll see some UI specific code in some.

My guidance is to follow the MVVM design pattern in most cases. On occasion a scenario will present itself where deviation may make sense. Weigh the pros and cons, make a decision and move on. Remember, you and your team members are responsible for delivering and maintaining the code.

In the next scenario you'll see two more examples of UI specific code in the code behind.

Data Driven Dynamic Form Scenario

The developer needs to render a data driven dynamic form. The form needs its behavior determined at run-time based on the source data.

The concrete example of this scenario in Cipher Text is the record editor. Each field in the form is data driven along with the field validation and casing rules.

FieldEditorViewModel & FieldEditorView

The FieldEditorViewModel adapts the CardField Model to the FieldEditorView. The CardField class implements IDataErrorInfo. This class has built in data validation rules and casing rules that run based on the FieldType and FieldCase properties.

AvailableFieldTypes and AvailableFieldCases properties are ReadOnlyCollections of OptionViewModels. OptionViewModel is a Generic class that Josh and I authored and described in our Creating an Internationalized Wizard in WPF article. OptionViewModel specializes in wrapping values from Enumerations, providing human readable descriptions and customized sorting of values. Additionally it simplifies programming with Flags Enumerations. OptionViewModel is another example of the power and simplicity of MVVM. A ViewModel effortlessly adapting a Model to the UI.

There are three Boolean properties that determine the state of the UI.

InSchemaEditingMode - This value is toggled when the user clicks the, "Modify Form" hyperlink on the data editor form. The DataEditorViewModel holds the collection of FieldEditorViewModels. The DataEditorViewModel handles the "Modify Form" command and iterates through the FieldEditorViewModels setting this property value. UI Elements on the FieldEditorView are bound to this property and display when the value is True.

IsFieldInEditMode - This value is toggled when the user clicks the, "Edit Field" icon. UI Elements on the FieldEditorView are bound to this property and display when its value is True.

IsMarkedForDelete - This value is toggled when the user clicks the red, "Remove Field" icon or the green check, "Restore Field" icon. When the value is True, a gray border overlays the field as in the below image.

Below are three instances of the FieldEditorView in three different states. The top Address field is expanded but is invalid because the Address field has not yet been filled in and it's a required field. The Phone field has been marked for delete. The Web Site fields are complete and can be contracted when the green check icon is clicked.

The green icon is really a XAML asset that I made that has a trigger data bound to the IsEnabled property of the button. The button's Command CanExecute method checks the Error property on the CardField to determine if the Command is enabled and the field can be collapsed.

The FieldEditorView is completely data driven. This unique and complex, yet powerful application feature was simple to design and code because of WPF's impressive data binding capabilities. This UI is also super simple to Unit Test because it's data driven.

Hiding Adorners

The red "!" indicates an invalid field and are displayed in the Adorner Layer of the TextBox as defined in the Validation.ErrorTemplate. However, if the user elects to delete a field that has one or more displayed adorners those adorner need to be removed otherwise it would display on top of the gray border.

The below OnIsMarkedForDeleteUpdated method is called when the Visibility property of the gray border is changed. If the FieldEditorViewModel.IsMarkedForDelete is True then the border is displayed and any adorners on the FieldEditorView are removed.

'HACK - this a one example of using MVVM View code behind.
'We need to remove any Adorners that are placed due to
' invalid an invalid field.
'By using data binding, we can tap into when the ViewModel
' sets the field up for removal and remove the Adorners.
''If the required programming task is UI only,
' then using code behind is fine.
'PrivateSub OnIsMarkedForDeletetUpdated( _
ByVal sender As System.Object, _
ByVal e As System.Windows.Data.DataTransferEventArgs)
e.Handled = TrueIf _objFieldEditorViewModel IsNothingThenExitSubEndIfIf _objFieldEditorViewModel.IsMarkedForDelete ThenDim objAdornerLayer As AdornerLayer = AdornerLayer.GetAdornerLayer(Me)
If objAdornerLayer IsNotNothingThen
ClearAdorders(objAdornerLayer, Me.txtFieldData)
ClearAdorders(objAdornerLayer, Me.txtFieldSortOrder)
ClearAdorders(objAdornerLayer, Me.txtFieldTag)
ClearAdorders(objAdornerLayer, Me.txtMaximumLength)
EndIfEndIfEndSubPrivateSub ClearAdorders(ByVal objAdornerLayer As AdornerLayer, _
ByVal objUIElement As UIElement)
Dim objAdorder() As Adorner = objAdornerLayer.GetAdorners(objUIElement)
If objAdorder IsNotNothingThenForEach obj As Adorner In objAdorder
objAdornerLayer.Remove(obj)
NextEndIfEndSub

FieldEditorView Commands

The Commands except for the GeneratePasswordCommand all simply changed data values in the ViewModel. The View reacts to changes in the ViewModel's data to correctly render itself.

The two below command methods contract and expand the field in and out of edit mode.

You'll notice that I make a sanity check by calling the corresponding CanExecute method. This is a good practice since there is no guarantee that another developer didn't just make a direct call to the method.

WPF and MVVM

This application shows off the symbionic couple WPF & MVVM. This natural application development style typified by smooth data flow from the Model to the ViewModel that is consumed by the View simplifies WPF application development and Unit Testing.

If you're coming from Windows Forms, ASP.NET or another event driven programming platform, it takes a little adjustment to grasp the full power and simplicity to code a WPF MVVM application where the UI reacts to data changes rather than event handlers that modify named controls. Give yourself time, write simple applications, you'll be so glad you did. Then convert a small application that you're familiar with, add the Unit Tests to the new application and take that to work on Monday and show off your new developer skills.

One area I've been paying special attention to is, memory profiling. I use the Red-Gate Ants Profiler. Ants has helped me understand .NET and memory management. You may see areas in my code where I have code something that at first glace you think, "why did he do that?" It was probably because I was memory profiling and found that some prudent clean up of objects prevented objects from hanging around in memory.

Comments and Discussions

Hi Karl,
I am only a novice with both WPF and MVVM so you will have to forgive me... to eliminate the code for VisibilityChanged_EventHandler in the View code behind, could you not use something like this as I have done with a DataGrid
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<!--
...
...
...-->
<DataGridHeight="121"ItemsSource="{Binding Blogs, NotifyOnTargetUpdated=True}"><i:Interaction.Triggers><i:EventTriggerEventName="TargetUpdated"><ei:CallMethodActionMethodName="VisibilityChanged_EventHandler"TargetObject="{Binding}"/></i:EventTrigger></i:Interaction.Triggers></DataGrid>
Now your TargetUpdated event is bound to the handler [VisibilityChanged_EventHandler] in the ViewModel again….
public void VisibilityChanged_EventHandler(Object sender, DataTransferEventArgs args)
{
// Handle event
}

I hate things like that last one as I am a little hard of seeing (and thinking) and I can never be sure I haven't missed something.

Henry Minute

Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
I wouldn't let CG touch my Abacus!
When you're wrestling a gorilla, you don't stop when you're tired, you stop when the gorilla is.

Thank you so much for the great article.But I have some question about the code in code behind.You said "If the code is UI specific and does not require Unit Testing then having the code in the code behind is fine."

I found many code in LoginDialog code behind,I think it will be a tough job when I want to change the UI logic.Additionally,I found lots business logic code which I think is not UI specific and should be put it in the business layer rather then the UI layer. Such as the code in "btnLogin_Click",

If Load() Then
Me.DialogResult = True
Else
_intLoginAttempts += 1
If _intLoginAttempts = 3 Then
My.Application.Shutdown()
End If
Me.txtPassword.Password = String.Empty
My.Computer.Audio.PlaySystemSound(SystemSounds.Exclamation)
End If

you assigned "3" to the attempt times, if i will remove this restrict one day, I must modify the UI layer.

Do I need to get my Model exactly right, before I can start in on the View and/or ViewModel?

The model is the data you would like to display and/or persist. This will change over the lifetime of most applications so getting it "exactly right" is not a requirement. If the model changes, chances are your ViewModel will also need to be updated to render the new data.

leah.hurst wrote:

Is there a skeleton of objects I can use - somewhat like a template - to sketch out an app to fill in?

There are some "mvvm starter kits" on the web, but coding them until you master MVVM is better for you long term.

The MVVM pattern and it's seperation of concern lends itself well to contract based programming. So, in response to "Do I need to get my Model exactly right, before I can start in on the View and/or ViewModel", it is not necessary to complete the implementation of the model before creating view/model, but a good approach is to agree (or create one yourself if working alone) on a contract (represented as an interface) that the model and viewmodel will both implement. Once the contract is defined, it doesn't matter what order the objects are created and they can even be created simultaneously.

As far as a skeleton template: since MVVM implementations vary a good bit, it is probably best to create your own template for your view models so they are all the same and you can create new ones quickly.

By having the project open in Expression Bend 3 + SketchFlow Spanish Version v3.0.1938.0 and want to see in the designer ApplicationMainWindowView.xaml Form
Exception occurs: Can not instantiate DataEditorView
StackTrace: Empty
Internal Exception: Could not find resource with name '(editingFormBackgroundBrush)'
Systems.Windows.Controls.Border Object Error in markup file
CypherText; component / View / dataeditorview.xaml Line 45 position 17
Also with the databaseViewOuterBorder Object Line 13 position 17

It would be possible to send Form without errors ???.-

Another query, if instead of saving an encrypted file, the application is connecting from the Login with a Database SQL Server 2008 (without encrypting the information), where the objects should be changed to accomplish this .-

You can write the objects to the database when the Save, Delete buttons are clicked.

aadisanto wrote:

Another query, if instead of saving an encrypted file, the application is connecting from the Login with a Database SQL Server 2008 (without encrypting the information), where the objects should be changed to accomplish this .-

The xaml file you want to view in the designer doesn't load because of other files like DatabaseView.

I never used the VS 2008 designer when working on this program. The VS 2008 designer does not work well with user controls that have resources. In VS 2010 this has been corrected.

Also the VS designer does not allow turning off areas of a xaml file like Blend does. So designing the main form using VS would not be fun. That is why I used the xaml editor and to develop this application.

For the past few years I've just been typing my XAML in the XAML Editor that comes with VS 2008. You can right click on any XAML file in the Solution Explorer, select Open With... and then set the Default to Source Text Editor. The designer will no longer open.

With the improvements in VS 2010, the designer works and loads much better than VS 2008.

By having the project open in " Expression Bend 3 + SketchFlow Spanish Version v3.0.1938.0 " and want to see in the designer ApplicationMainWindowView.xaml Form
Exception occurs: Can not instantiate DataEditorView
StackTrace: Empty
Internal Exception: Could not find resource with name '(editingFormBackgroundBrush)'
Systems.Windows.Controls.Border Object Error in markup file
CypherText; component / View / dataeditorview.xaml Line 45 position 17
Also with the databaseViewOuterBorder Object Line 13 position 17

It would be possible to send Form "ApplicationMainWindowView.xaml" without errors ???.-

I couldn't find any other means of contacting you - for a good reason, I suppose - so I try it this way.

I am involved in quite an interesting open source project, called CrypTool. Our aim is to make cryptography comprehensible to 'anyone'. We are currently working on a re-development from scratch, which is based on .NET and WPF.

After I saw your password management project, and followed some more links to your other projects, I hoped that I could probably spark your interest in CrypTool 2 and win you as a volunteer for our project. I am very much impressed of your work and pretty sure that you receive this kind of request quite often. However, I would appreciate if you could have a look at our project websites, and potentially get back to me.

We not only search for active software developers, but also appreciate experienced people who are willing to familiarize with our code base and support us in the architectural design.

My question:
In your DataEditorViewModel you use a confirmation message.
"Application.ConfirmAction("Delete Card", "Are you sure you want to delete this card?")"
How would you write a unit test for testing the behaviour of DeleteExecute() Command?

The way this is authored, unit testing would be a bummer. At the time I wrote CipherText I didn't have an "MVVM" way of calling dialogs and getting a response. Notice that I called a method rather than the MessageBox itself. That was by design.

I need to update CipherText and will try in about two weeks when I get back from London.

Hi karl,
Great article! I am fairly new to WPF and ofcourse MVVM too. I am a C# programmer so at places could not understand things, but i loved the way you divided the UI into several ViewModels.
I had a few doubts over this article.
You MainAppViewModel consists of two ViewModels:
- Collection of CardTypeCommandViewModel
- DataEditorViewModel

When you click on "+" on any single Card in CardTypeCommandViewModel, How does the DataEditorViewModel get the CardType which initiated the action?

In your XAML for its View, you do have a command binding to FilterCommand.But I do not see the execute method?

The logical way that i would think it should be happening is, on clicking "+" the command travels from CardTypeCommandViewModel to MainAppViewModel and then to DataEditorViewModel supplying it with the CardType to be added.

I am interested in how you communicate between ViewModels. I am trying to develop an application, and sometimes i feel i am dividing my ViewModels into very small small ViewModels to keep my code clean.But then commanding becomes difficult.

Thanks Karl, I had several "aha" moments once i started digging deeper.
The magic is RelayCommand class.
I might be repeating this, but I jsut want to make sure i got it right.. Please correct me if i am wrong.
You Have ApplicationMainWindowViewModel which contains collection of CardTypeCommandViewModel.
Each CardTypeCommandViewModel contains ICommand instance which is really a Relay Command, whose CanExectue and Execute method are in the ParentViewModel that is ApplicationMainWindowViewModel. So even though the command is in CardTypeCommandViewModel , it really exectues in the ParentViewModel.

That is what i was precisely looking for, command binding in childViewModel but it is really getting executing at the parentViewModel.

I had a question on how to handle asynchronous data binding. Tradditionally, I would add ObjectDataProvider element to the XAML with the IsAsynchronous="True" attribute. How do you recommend handling this with the ViewModel?