Showing posts with label XAML. Show all posts
Showing posts with label XAML. Show all posts

Sunday, July 7, 2013

Changing Culture in WPF

I know my blog has been a bit empty over the last 6 weeks or so.  I've been working heavily on my C# Interfaces course for Pluralsight which released last week.  So now it's time to catch up on some articles that I've been intending to write.

This time around, we'll look at a bit of a hack that makes changing the culture in a running WPF application a bit easier than the majority of the solutions out there.  The sample project can be downloaded here: http://www.jeremybytes.com/Downloads.aspx#WPFCC.

Using the Machine Culture is Easy
.NET provides us a fairly straightforward way to support different languages and cultures in our applications. By default, our applications use the culture for the machine that they run on.  This means that if we provide resource files with different strings (or images or whatever) that are appropriate for a language, we get the behavior basically for free.

For example, we can provide a resource string in a resx file:


We have resource files set up for "en-US", "en-GB", and "en-AU":


Then in our XAML code, we just need to reference that resource string rather than providing a hard-coded string:


Notice that our "Text" property of this TextBlock references the static "Greeting" string resource.  So, when our application runs, it will automatically get the culture-specific value.

Here's the output:


And we can see "Howdy, Y'all!" is used in our TextBlock.  If our machine is set to a different culture, then we would get that culture-specific string (or the default culture if it's not available).

Note: This isn't a tutorial on how to localize your application, so you'll need to dig into that yourself.  We're just getting the basics in place so we can look at the "hack".

[Update Jan 2014: If you do want to learn how to localize an application in .NET, you can check out my Introduction to Localization and Globalization in .NET course available on Pluralsight.]

Changing the Culture is Hard
So, we've seen how easy it is to use the machine culture.  And, in fact, it's not hard to put in a custom culture (different from the machine) as the application is starting up.  But if we want to change the culture while the application is running, we run into a bit of a problem.

The "free" behavior that we get above (culture-specific resource strings from a file) only happens when the WPF window is being created.  This means that even if we change the culture of our thread while our application is running, the open windows will continue to use the already-bound resource strings -- no automatic updates.

The Scenario
The first question you might ask is "Why do we want to change culture in a running app?"  Well, I ran across this issue while helping a friend working on a project.  He was building a kiosk application in WPF that needed to support multiple languages.  The idea is that the user would walk up to the kiosk, press the button for the language they wanted, and then go from there.

If you cruise the internet, you will come across some interesting solutions.  Some people have built libraries where you call a method to rebind all of the resources of an open window.  I'm not a big fan of this solution just because it seems overly complicated.  And some of the libraries required you to put an attached property on all of the UI controls.

The most basic recommendation to change the culture of your application is to shut down and restart the app.  The idea behind this is that you update a configuration file with the new culture that you want.  Then you restart the application (which is never as easy as it sounds).  When the app starts up, it uses the new culture from configuration.

The "restart" solution sounded like the better solution of these two, but then I had a kind of crazy idea.

The Application MainWindow Property
In my sample code for my session on Dependency Injection (Dependency Injection: A Practical Introduction), I manually create the MainWindow for a WPF application.

Here's what the simplified code looks like (from App.xaml.cs):


The Application.Current.MainWindow is a property on our application that tells us what the main window is.  When the main window is closed, the application itself shuts down.  In this example, we create a new instance of the MainWindow class (which is defined by MainWindow.xaml) and then assign it to the MainWindow property of the application.  Then we Show the MainWindow.

The effect of this is that the MainWindow class is shown.  And when it is closed, the application shuts down.

So, I started to wonder if we could hack around with the MainWindow property a little bit so that we could simply create a new window (with a different culture) rather than shutting down the entire application.

The Hack: Resetting the Main Window
In the App.xaml.cs file, I added a new static method that would swap out the main window of the application.  Here's the code:


Let's step through this.

First, we set the CurrentCulture and the CurrentUICulture for the current thread.  The CurrentCulture defines the culture that the thread operates on.  The CurrentUICulture determines which resource file is going to be used.  For example, if we set the CurrentUICulture to a CultureInfo for "en-US", it will use the resources that are defined in the "Resources.en-US.resx" file (which gets translated into its own assembly/folder when the app is compiled).

We want to set the CurrentUICulture *before* we create the window.  This makes sure that the correct resources will be picked up.

After setting the culture, we create a local variable ("oldWindow") that points to the currently assigned MainWindow. We grab a reference so that we can programmatically close this window later.

Then we create a new MainWindow instance (again, this is coming from MainWindow.xaml).  This will be created with the resources for the new culture.  We assign it to the MainWindow property, and it becomes the main window for the application.

Next, we show the (new) MainWindow.

As a last step, we close the "old" window -- the one with the previous culture.  Since this is no longer the application's "MainWindow", it does not shut down the application.

The result is that the application will have a noticeable "window opening / window closing" effect, but we've managed to do this without shutting down the application.

The Results
Let's see the result in our sample application.  First, as we've seen, we have a TextBlock that uses the "Greeting" resource string.  In addition to that, we have 3 other text blocks.  In the code, we show the current culture, and we assign a date to display with both the short date format and the long date format.

Here's the code for that:


"displayDate.ToString("d")" gives us the short date format, which is "MM/dd/yyyy" in en-US.  "displayDate.ToString("D")" gives us the long date format, which is "dddd, MMMM dd, yyyy" in en-US.

We also have 3 buttons to change the culture.  Each button is similar.  Here's the click handler for the "US" button:


We can see that this calls the ChangeCulture method we looked at earlier.  This will re-create the window.  The constructor of the MainWindow calls "UpdateUIElements" to put the appropriate values in the text blocks.

Here are the outputs if we click each button in turn:




We can see that the "Greeting" text is different for each window.  Also, the short date and long date formats are appropriate to the culture.

As a bit of a humorous side note: I originally used today's date for the sample.  But since today is July 7, 2013, it would be very difficult to tell the difference between "07/07/2013" and "07/07/2013".

Wrap Up
So, this is a bit of a hack to re-create the main window for a WPF application.  But it is easier than restarting the application with new configuration values.  And with the kiosk scenario, it isn't a problem if we "reset" the entire application when the language is changed.

You might be able to use this same hack in a Windows Forms application (although getting to the application is a little less straight-forward).  It may also work in Silverlight by resetting the RootVisual (but I have not tried that).  I seriously doubt that it would work in a Windows 8 App Store app; this is also based on speculation since I have not done much with those types of apps.

Sometimes we come up with creative solutions to specific problems.  This one probably isn't very widely applicable, but it's fun to see what we can come up with nonetheless.

Happy Coding!

Sunday, July 8, 2012

Metrocizing XAML: Part 2: Control Templates

In Part 1, we saw how we could update the look and feel of our XAML applications by changing a bit of layout and our Data Template.  This time, we will take things a step further.  First, we'll do a quick overview of some of the minor changes (colors and general layout), and then we'll dive into creating a custom control template for our buttons to make them more Metro-ish (Metroid?).  As a reminder, here are the UIs of our "old" and "new" applications:

Old Layout

New Layout

The source code for both of these projects is available here: Jeremy Bytes - Downloads.  These applications are in the "Old.UI" and "New.UI" projects respectively.

Application-Level Updates
Several of the updates to the application have to do with the general layout and colors.  You can check the XAML for more details on this.  The key features are the re-arrangement of the grid (swapping the ListBox and Button panels), removal of the background gradient, and the insertion of a solid background.

As mentioned in Part 1, the resources for the application (brushes, data templates, and value converters) were moved from MainWindow.xaml to the App.xaml Resources section.  Let's start by looking at the top of our App.xaml (from New.UI):

The first thing to note is that we have moved our Value Converters from MainWindow.xaml to here.  This was necessary because several of the value converters are used in the ListBox Data Template that is also in this file.  To bring in the Value Converters, we needed to add the namespace for the local project (so we can access the classes in Converters.cs).  For more information on Value Converters and how they get added, please see Introduction to Data Templates and Value Converters in Silverlight (also works in WPF).

The next section contains brushes for our application.  There were no resources for these items in the old application.  I added them here so that it would be easy to update the application colors in the future (since Metro-ish applications will go out of style sometime in the future).  Notice that I named the resources after what they are used for and not what colors they are.  If I had named the resource something like "LightGrayBrush", then it would be difficult if we wanted to change it to another color.  Since the name describes what the brush is used for (rather than what it looks like), we can change this to blue in the future without worrying about mis-matched names.

These application brushes are tied to the XAML in MainWindow.xaml (such as setting the application background).  And, as we'll see, these are also used in our control templates for the buttons.

Let's see what else is in the App.xaml (sections are collapsed to get the overview):

First, we have a Control Template and Style for our "GoButton".  We'll be spending quite a bit of time in this detail below.  Next, we have a Control Template and Style for our "ClearButton".  The buttons differ in the icons (an arrow vs. an X), but they otherwise behave the same.

Next we have 3 different TextBlock styles for "ApplicationText", "ListItemTextStyle", and "ListTextStyle".  We saw the ListItemTextStyle and ListTextStyle in use in our Data Template in Part 1.  Finally, we have our Data Template for the ListBox.  We looked at this in detail in Part 1.

Comparing Buttons
So, what are the differences between our old and new buttons.  Let's compare them side-by-side:

Old Button

New Button

One big difference is operation.  The old button is only clickable on the part that looks like a button (the "Fetch" part).  The new button is clickable anywhere in the rectangle.  This makes it much friendlier to touch-enabled applications since it is a much bigger target.

Let's compare the XAML, starting with the old button in MainWindow.xaml (in Old.UI):

Notice that we have a border that encloses a StackPanel.  And that StackPanel contains a TextBlock and an actual Button.

Compare this to our new XAML (in MainWindow.xaml in New.UI):


The difference is here we just have a Button with the content of "Concrete Class".  So, where's the rest of it (the border and the icon)?  That's all part of the custom Control Template.  And it's getting applied to this button through the Style property.

The Button Style
As we saw earlier, the GoButtonStyle is in the App.xaml.  Now, let's take a look at the details:


The Style allows us to apply settings to properties centrally.  We have 2 buttons in our application that use this Style (the "Concrete Class" button and the "Interface" button).  But we only have to set these properties once.  And if we decide that we want to change something (like the FontSize), we just update it here, and it automatically propagates to all buttons that are using this Style.

Notice that the "Foreground" and "Background" properties are set to our "Application" brush resources that we set above.  This is important.  We want our buttons to have the same background as the application.  If the application background changes, we want our button background to change along with it.  (Note: this might not always be the case, but that's the behavior that we want here.)

Finally, we have the "Template" property set to the Control Template that's also in our App.xaml.

The Button Control Template
Before we look at the specifics of the GoButton Template, I want to say a few words about Control Templates.

As mentioned in Part 1, XAML controls are "lookless".  This means that the behavior is completely separated from the visual display.  We are provided with default templates (so that we don't have to create our own), but the templates are fully customizable and/or replaceable.

Control Templates are generally very complex.  They are designed to handle a variety of states.  For example, a button has a number of states, including "Normal", "MouseOver", "Pressed", "Disabled" as well as "Focused" and "Unfocused" (in addition to others).  If you want to have all of these features available, then it's often easiest to use Expression Blend to export the current control template for you to modify.

In our case, we are only handling a subset of these states (Normal, MouseOver, and Pressed), and we don't worry about the other states (since they aren't really applicable to our application).  One thing to note: just because we do not implement a visual change for a State does not mean that that State does not exist. For example, our control template does not implement "Disabled", but our button can still be disabled -- it just won't look any different from an enabled button.  Same with "Focused" -- the button itself still supports the idea of "focus", but it will not look any different if it is focused.

If we were creating a set of custom templates to be used more extensively, then we would definitely want to implement all of these states.  As it is, we'll just focus on the ones we care about for this application.

Control Template Overview
Our Control Template is more complex than other bits of XAML that we've seen so far, so we'll break this down into several different pieces.  First, let's look at an overview of the Control Template with several of the areas collapsed:


First, we have the ControlTemplate tag.  The TargetType lets us know what kind of control this applies to.  This template can only apply to Buttons.  If we were to try to apply it to a TextBox or ListBox, we would get an error.  The Key let's us reference this like any other Resource.

Our outer element is a Grid.  This is there primarily to hold the other elements; we don't have any Rows or Columns defined at this level.

Inside the Grid is the VisualStateManager.  This is how we provide different looks for the States that we mentioned above.

The Border is the first visual element.  We'll take a closer look at the details of this in just a moment.  Inside the Border, we have Grid for layout purposes.  This Grid has both Rows and Columns and contains our ContentPresenter and our Canvas.  We'll see more details on these in just moment as well.

Now, let's go through each of these parts.  We'll start with the primary elements and then swing back up to the VisualStateManager at the end.

The Button Border
Here is the complete markup for the Border (the outer edge of our Button):


Notice that the BorderBrush property is set to a "TemplateBinding".  The TemplateBinding markup extension indicates that this should be bound to one of the main properties of the Button.  In this case, we want the BorderBrush to be the same as the Button's "Foreground" property.  And remember from our Style, the "Foreground" is set to the "ApplicationTextForeground" by default.  But this can be changed.  If we change the Button's Foreground property (either in the property inspector or in the markup, then the BorderBrush will change along with it.

The Border Background property is a little bit different.  Notice that we have a SolidColorBrush that is set to the TemplateBinding of Background.  This let the background color change if the Button Background property is updated.  Notice also that we have a x:Name on our brush (ButtonBackgroundBrush).  We gave this element a name because we will use it in our VisualStateManager -- when the State changes, we want the Background to change.  We'll come back to this.

The Button Main Layout Grid
The next element is the Grid which has our main layout for the Button:


Let's look at our button again:


The Grid defines where we will place our elements.  The first Grid Row/Column contains the "ContentPresenter".  The ContentPresenter is responsible for displaying whatever is in the "Content" property in the Button.  In our case, the Content is simply text ("Concrete Class").  We use a ColumnSpan of 2 so that the content can stretch the full width of the Button.

Notice that our ContentPresenter does not have any sort of Font information included.  Any text that appears in the ContentPresenter automatically picks up the Font information from the Button itself.  Since we have all of that information set on the Button Style, we don't need to worry about it here.

As a side note, if we tried to put more than just text into the Content property, our Button would probably behave strangely.  This is another area that you need to look into further if you are interested in creating your own button templates that can be used in a variety of situations.

The Canvas is in the second Grid Row/Column and contains our arrow.  Since the Row/Column definitions are set to "Auto", this will only be as big as the contents.  Since the first column is set to "*", it will take the remaining space.  The result is that our icon will be aligned to the bottom right side of our Button.

The Arrow Icon
For the Arrow Icon, we could have used a graphic, but that's generally not the best approach.  XAML is designed so that things can be easily resized, stretched, or re-flowed to fill in available space.  The best way to make sure that your controls can handle stretching/resizing is to use vector descriptions rather than a .gif or .jpg.

I shamelessly stole this arrow from Laurent Bugnion's blog: 56 Vector Arrows in XAML (isn't the Internet great?).  This blog article includes a bunch of different arrows (56) that are all described in XAML paths.  I found one that I liked, did a little cutting, and pasted it into my application (then tweaked the colors a bit to fit the style).

I won't show the entire output (since a lot of it is a list of numbers for a Path), but here's the relevant bits:


For the Path statements that make up the arrow and the circle, I made a couple of changes.  First, I set the "Fill" property to a TemplateBinding to match the Foreground of the Button.  Then, I changed the Opacity to "0.5".  This will make the arrow semi-transparent (with the effect of a lighter color).  This means that the arrow icon will look lighter than the Button text even though they are the same color.

The "Data" property contains the meat of the path, specifying all of the points in the arrow and circle.

The Visual State Manager
Now that we've see all of the default visual elements, it's time to look at the VisualStateManager.  This determines what our Button will do when the various states change.  Again, what we have here is very simple; we could make this much more interesting/complex very easily.


Our VisualStateManager has a number of VisualStateGroups.  The States that we care about are all in the "CommonStates" group, but the Button also has "FocusStates" and "ValidationStates".  The reason there are different groups is to allow for overlap.  For example, we could have a button that is both "MouseOver" (from the CommonStates) and "Focused" (from the FocusStates).

Since we only care about the CommonStates, we just have one VisualStateGroup in our Control Template.  Inside the group, we have 3 different VisualStates.  Each VisualState determines what will happen when the control enters that state.  In each of our VisualStates, we have defined a Storyboard with an Animation of Duration zero.  This means that we are animating a property (the background color), but the zero duration means we have no "transition" -- the color change happens immediately.  If we wanted to be more creative with our transitions, we could add additional animation (such as pulsing when the control is focused).

Our three VisualStates all set the same property.  Notice that the Storyboard.Target is set to the ButtonBackgroundBrush.  This is the name of the brush in our Border.Background that we saw above.  Then we have the Storyboard.TargetProperty which specifies what property we want to set.  In this case, we want to set the "Color" of the brush.  Finally, we have the "To" that specifies the new value for the property.

For the "Normal" state, we set the color to the "TemplateBinding Background" (which is the default background color we want).  For the "MouseOver" state, we set the color to LightSlateGray, and for the "Pressed" state, we set the color to "White".  (Note: we would probably want to set these to resource colors or TemplateBindings for a more robust Control Template.)

When we put all of these elements together, we get the visual layout and state-change behavior for our GoButton.  The template for the ClearButton is very similar.  The primary difference is that instead of using a set of Paths for the icon, it simply uses a large letter "X".  Again, for a production application, we would probably want to take a little more time to do a vector graphic.  But this works for our simple case.

Putting It All Together
So, now that we've looked at the updated Data Template, Value Converter, Application Brushes, Styles, and Button Control Templates, we can see how these pieces all fit together to form the fresh look of our application:


And remember, we did all of these changes without modifying our Application code -- the application behaves just like it did before (loading in data from a web service and displaying it in a ListBox).  And now we have a completely new look with about a day's worth of effort (and a lot of that was experimenting with colors and layout).

XAML is pretty awesome, huh?

Happy Coding!

Metrocizing XAML - Part 1: Data Templates

Let's face it: gradients and glassy buttons just aren't "cool" anymore.  In a way, it sucks; these applications aren't that old (just a year or two).  But now they look dated.  And this is what makes XAML awesome.  Since XAML is "lookless" (meaning that the visual representation of the controls is separated from the underlying operation), we can rip out an old look and drop in a new one without needing to change our application code.  And if we have proper separation of the thematic parts of our application, those updates can be isolated to a single location.

As I mentioned a couple weeks ago, I went through several of my sample projects and "metrocized" them.  Since these are XAML solutions (several WPF and one Silverlight), the updates were not complicated.  Let's take a look at an "old" and a "new" screen together.  These are taken from the IEnumerable, ISaveable, IDontGetIt: Understanding .NET Interfaces samples (specifically the IEnumerable.sln).

Old Layout

New Layout

These projects are available for download in a combined solution here: Jeremy Bytes - Downloads.  The "Old.UI" project contains the old layout; "New.UI" contains the new layout.

XAML is Awesome
The best part of this whole process is that XAML completely separates the visual display from the controls themselves.  This gives us the chance to change the way our application looks without having to change the underlying code.  And as we go through this example, we'll see just that.  We didn't need to change any of the application code. (Note: There is one small change to the Value Converter code; but this was done to put some different colors into the converter.)  The rest of the updates are in the XAML itself.

One thing to note: I am not a UX designer.  I put together passable user interfaces that are pleasing and functional, but I'm not one of those UI wizards (you know who I'm talking about -- the guys that come up with incredible designs, and you smack yourself on the forehead: "That's so obviously awesome!").  I put together the bulk of the design updates in about half a day (colors and layout).  It took me a little longer to iron out some of the kinks in the Control Templates.  Once the hard part was done, implementing the changes in the different application was very easy (mostly just replacing XAML in the right places).

We'll be looking at these updates in 2 parts.  The first part (this one) will cover the updates to the ListBox -- the one with the Person objects listed.  This is primarily concerned with the Data Template used by the ListBox, the Value Converter for the color, and a few other minor updates.

The second part (next time) will cover the updates to the Buttons.  Our original application used the standard button look-and-feel.  The new application uses a custom control template.  With the control template, we control the layout, the design (such as the arrows), and also the display behavior -- although you can't see it in the screenshot, the buttons have different colors when you hover over them or click them.  This template is fairly simple (compared to how far you can go with control templates), but it has the effect that I was looking for here.  We'll walk through this sample in Part 2.

ListBox Updates
The ListBox itself stays pretty much intact.  The primary differences are the placement in the application Grid (on the right instead of the left), and the inclusion of a WrapPanel -- this gives us the ability to show multiple columns in our ListBox.  Let's compare our old and new markup to see the changes.

First the old markup (from MainWindow.xaml in Old.UI):

Now the new markup (from MainWindow.xaml in New.UI):

The primary difference is the addition of a WrapPanel.  We did this by adding tags for the ListBox.ItemsPanel and the ItemsPanelTemplate.  By using the WrapPanel, we are specifying that if we run out of space, to "wrap" the list to another column.  The WrapPanel has an Orientation property to determine whether to wrap vertically or horizontally.  "Horizonal" is the default, and so that is the direction we have here.

Normally, a ListBox would just scroll in order to accommodate any items that don't fit on the screen (either horizontally or vertically).  Because we have our wrap panel going horizontally, we need to disable to built-in horizontal scrolling of the ListBox (otherwise, it won't actually "wrap" to the next row).  This is why we added the "ScrollViewer.HorizontalScrollBarVisibility="Disabled"" attribute: to disable horizontal scrolling.

The items in the screenshots are in the same order: John Koenig, Dylan Hunt, John Crichton, Dave Lister, John Sheridan, Dante Montana, Isaac Gampu.  If we look at the new sample, we see that Dylan Hunt (the 2nd item) comes horizontally after John Koenig.  Then we "wrap" to the next line for the 3rd and 4th items).

If we wanted to wrap vertically (so the items go down the first column, then down the second column), we would simply set the WrapPanel Orientation to Vertical, and then disable the Vertical scrollbar on the ListBox.

A Note About the WrapPanel
The WrapPanel is a standard control in WPF 4 (Visual Studio 2010).  If you are using Silverlight (4 or 5), the WrapPanel is available as a separate download as part of the Silverlight Toolkit.  I used this same ListBox layout in a Silverlight 5 application, and it worked just the same as the WPF version.

The ListBox Data Template
So, the updates to the ListBox itself are not very extensive, but the items are displayed completely differently.  This is because we are using a separate Data Template to control the layout.  This is denoted in our markup by the ItemSource = {StaticResource PersonListTemplate}" attribute.

If you are not familiar with Data Templates, I would highly recommend that you take a look at Introduction to Data Templates and Value Converters in Silverlight (this works the same in WPF).  This covers the creation of the Data Template that is used in the "old" application.  We'll just be looking at the differences here.

The Old Data Template
First, let's review the old Data Template.  This is located in the Resources section of MainWindow.xaml (in Old.UI):


Just a few notes here: first we have a Border that surrounds our entire template.  The BorderBrush is databound to the StartDate property of the Person object.  This goes through a Value Converter (myDecadeBrushConverter) to turn the date into a brush.  The result is the border color of each item is determined by the decade of the StartDate property (different colors for 1970s, 1980s, 1990s, and 2000s).

The rest of the Data Template is described in the article mentioned above.  Basically, we have a collection of StackPanels and TextBlocks to layout the data in the format that we want.

Here are the results for Dylan Hunt:

The New Data Template
The new Data Template is a bit more complex.  The first thing to note is that it is no longer in the MainPage.xaml file.  The Data Template (along with all of our other resources) have been moved to App.xaml.  The App.xaml Resources section gives us a place to put resources that are available to our entire application.  In this sample, we only have one screen, so we don't get much from sharing.  But we do get a big benefit from centralizing all of our "theming".  If we want to change the look in the future, we only have this one place to look (rather than in the separate XAML files).  Managing Resources is a bigger topic with lots of options (such as creating completely separate resource dictionaries and assemblies).  If you're building larger applications or a suite of applications that all share the same "look", then you'll want to check into this further.

The first part of the new Data Template contains the Border element (from App.xaml in New.UI):

The big change here is that we are no longer binding to the BorderBrush property, we are binding to the Background property.  This gives us our different color backgrounds for each item.  The Value Converter has also been updated a bit (for the new colors and a bit of optimization).  We'll take a look at this in just a bit.

Next, since our layout is a bit more complex, we have a Grid to help us layout our controls:

This gives us 3 rows and 2 columns to work with.  Then we have the main layout of our controls:


Again, nothing too unusual here: we're just using StackPanels and TextBlocks like we did before, just with a different layout.

The Styles for the items have been broken out (also in App.xaml of New.UI):

This lets us control the Font properties and alignment separately.  If we change our minds about these settings, we can just update the Styles, and our controls will pick them up automatically.  Note here that we are using "White" text since we have a contrasting background color.

Here's the result for Dylan Hunt:

Updates to the Value Converter
We also made some updates to the DecadeBrushConverter.  This converter returns a Brush object based on the decade of a DateTime property.  Our old converter controlled the Border color; the new converter controls the Background color.

Let's look at our original converter (in Converters.cs in Old.UI):

The original Value Converter used a series of "if" statements to determine whether the DateTime value was part of a particular decade.  If so, then it returned a SolidColorBrush with an appropriate color.

The new converter has been refactored just a little bit.  Here's the new code (in Converters.cs in New.UI):

The biggest functional difference is in the colors that are returned.  Rather than being the primary colors of the old border, we have selected more "Metroid" colors for the background.

The change from the series of "if" statements to a "switch" statement was made due to cyclomatic complexity.  If you have Visual Studio 2010 Ultimate, you can calculate the Code Metrics for a project (under the "Analyze" menu).  One of the items is the Cyclomatic Complexity.  This value is like golf scores: smaller is better.  The cyclomatic complexity basically tells how many different possible code paths exist in the code.

With the series of "if" statement, the cyclomatic complexity was increased because we have 2 conditions in each "if" (the year is greater than or equal to one value and less than another value).  In our refactored code, we calculate the decade before running through the decision process (by doing integer math, when we divide by 10 we lose the last digit; when we multiply by 10 we add a "0" back on -- this gives us the decade).  Since we have the decade already, we can use a "switch" statement which only has 1 condition for each item (instead of 2).  This reduces our cyclomatic complexity even though our ultimate output is exactly the same.

As a bigger benefit, I think the second version is easier to read (but that's just a personal preference).

Changing the Look with XAML
So, we went from this:

to this:

without changing any of our application code.  All we had to do was update our XAML and our Value Converter.  That's pretty cool.

Next Time
Today, we looked at how we can update XAML Data Templates to give us a completely different look to our ListBox -- without changing the application code at all.

Next time, we'll look at how I created the control templates that are used for the buttons.  The old solution just used the default button templates, but we'll be able to see the changes from a combination of border, text, and button to a single custom-templated button that matches our Metro-ish style.

Happy Coding!

Sunday, June 17, 2012

Updated Samples for Code Camp

So Cal Code Camp - San Diego is coming up quickly (next Saturday & Sunday).  Be sure to check the schedule and stop by one of my sessions if you can.

I've updated the sample applications with all new XAML -- they are now a bit more "Metroid".  Here's a comparison between the old and new sample for my talk on Interfaces:

Old Repository Interface Sample

New Repository Interface Sample

The UI re-design does not affect the code that drives the applications; one of the great things about XAML is that you can update the UI to look however you like and still keep the underlying functionality.  The updated code can be downloaded from my demos page: http://www.jeremybytes.com/Demos.aspx.

In a future article, I will cover the custom templates (control templates and data templates) that I used to create the updated look.

Even if you don't attend one of my sessions at Code Camp, be sure to stop by to say "Hi" sometime during the weekend.  One of my goals at Code Camp is to talk to as many developers as possible -- both old friends and new friends.  See you there!

Happy Coding!

Sunday, April 22, 2012

Overview of the MVVM Design Pattern

The Model-View-ViewModel (MVVM) design pattern gets a lot of attention (as well it should).  The pattern itself is fairly straight-forward.  Where many developers  get stuck (especially developers just walking up to the XAML world) is with the implementation.  Often developers walk up to a framework/toolkit that offers help with implementation of the MVVM pattern, and they get mired in the intricacies of the particular framework without understanding the pattern itself.

The frameworks are important.  They offer libraries that make the implementation of the pattern cleaner by encapsulating functionality that is not offered in the underlying XAML engine.  What is more important is that we have a good understanding of the pattern itself before diving in to one of these frameworks.  If we understand the "why" of the pattern, then we are less likely to make pattern-breaking errors when we get to the "how" of the implementation.

In a previous article (XAML App Review - Part 5: MVVM and Wrap Up), we took a very quick look at MVVM.  Today, we'll dive deeper into the pattern itself: a little bit of history, the problem spaces that it is designed to resolve, the various parts that make up the pattern, and some consequences of using the pattern.  In a future article, we'll look at a sample implementation of the pattern in a XAML-based application.

A Little Bit of History
The MVVM pattern is based on the concepts of previous Presentation design patterns including MVC (Model-View-Controller) and MVP (Model-View-Presenter).  The MVC pattern was developed before the RAD tools that we use today, when the developer had to build the UI elements from scratch (or bring them in from a shared library).  Andrew Hunt and David Thomas describe the key concept of MVC as "separating the model from both the GUI that represents it and the controls that manage the view" [Andrew Hunt and David Thomas, The Pragmatic Programmer, Addison-Wesley, 1999].

These patterns have moved forward into our modern tools (as with ASP.NET MVC).  As we can tell from the names, these patterns share common ideas: the Model and the View.  We will discuss each of these in more detail below.

The MVVM pattern is a variation on the MVC and MVP patterns based on the presentation model of XAML.  XAML offers a very rich binding mechanism, and the MVVM pattern uses this binding mechanism as the "goo" that holds everything together.

A Bit of Review
Christopher Alexander gives us a definition of design patterns that we use today:
Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over without ever doing it the same way twice. [Alexander, et al., A Pattern Language, Oxford, 1977]
One of the important parts of this definition is that a pattern describes a core of the solution.  The pattern does not describe a particular implementation.  There are tons of frameworks that help us with implementation: Prism, Caliburn, MVVM Lite, and many, many others.  These all assist us with implementing the MVVM pattern (and as noted, we may be most successful with one of these frameworks), but no implementation is the pattern itself.

For more information on Design Patterns in general, please refer to Learn the Lingo: Design Patterns.

For simplicity, we'll stick to the four basic parts of a design pattern: Pattern Name, Problem Space, Solution, and Consequences.  We've already seen the Pattern Name: Model-View-ViewModel.  We'll see how this describes the different components as we get to the Solution.  Normally, we would describe the Problem Space before the Solution, but because of the nature of the pattern, it will be easiest for us to look at the Solution first.

MVVM: Solution
As the pattern name implies, the MVVM pattern consists of three primary components.  Note: I'm using the word "component" here in the generic sense ("parts" or "pieces").  After taking a look at each of the components, we will see how they interact with each other.

Model
The Model encapsulates the business logic and data that is used by the application.  The best way to think of the Model is everything that is not Presentation -- when using a layered application approach, it is everything below the presentation layer (which may include a business layer, service layer, data access layer, data storage layer, etc.).  In most scenarios, our Model will be abstracted into various components.  For example, we may have a repository that is responsible for retrieving and persisting objects through a service, and the service is responsible for interacting with the data store (such as a database).  And what types of data objects are exposed will vary; they may be smart objects (if we are doing Object Oriented Programming) or data entities (if we are doing Entity or Domain-Based Development).

The actual implementation of the Model is not important to the overall MVVM pattern, although the implementation of the objects in the Model may affect how the objects are exposed in the ViewModel.   The Model should not have any presentation logic.

ViewModel
The ViewModel encapsulates the presentation logic and the data that is used by the View.  We can think of this as the "goo" that holds things together.  MVVM is designed around the powerful data binding engine that is available in XAML.  The ViewModel is responsible for taking the data objects that are available in the Model and making them available as properties to which the View can data bind.

But the ViewModel is responsible for more than just exposing Model objects as properties.  It also provides properties that are used for the presentation logic of the application.  For example, lets say that we have an Order object, and whether it is read-only will depend on whether the order has already shipped.  The Model would handle determining the read-only state of the object (since this is part of the business logic), but then the ViewModel could expose an OrderReadOnly property that the View can use.  The View can then bind the IsReadOnly property for a particular control (or set of controls) to the OrderReadOnly property of the ViewModel.

The ViewModel also handles any interaction between the View and the Model.  This is accomplished by exposing methods or commands that the View can call.  The ViewModel then uses those methods to make calls into the Model.  We'll take a look at this more closely in the Interactions section below.

View
The View is what the user sees on the screen -- all of the UI elements.  This is the collection of XAML elements that make up the user interface (user controls, buttons, labels, text boxes) as well as the supporting items that assist these elements (styles, animations, control templates).

As we've seen, MVVM is based on XAML data binding.  This means that our view is usually chock-full of data bound attributes.  As noted in the ViewModel description above, this is not limited to data, but also other properties that affect interaction.  For example, we may have a TextBox that has its Text property is data bound to a property in the ViewModel (such as OrderDate).  But that same TextBox may also have its IsReadOnly or IsEnabled property data bound to properties in the ViewModel.  We can even have visual properties like FontSize or Foreground determined by data binding to ViewModel properties (along with appropriate value converters).

Separation of Concerns and Interaction
Now that we've seen the components and what they are responsible for, let's take a look at how they interact with each other.

The View only knows about ViewModel.  The View does not have any direct knowledge of the Model. It only knows about the ViewModel.  The View is generally responsible for creating the ViewModel, and this is almost always a one-to-one relationship.  In an ideal world, the View would not have any code-behind (but some people are more adamant about this than others -- it depends on the implementation).

The ViewModel knows about the Model.  The ViewModel is responsible for retrieving any objects that it needs to expose from the Model.  This can be a one-to-one or one-to-many relationship.  An example of a one-to-one relationship may be a ViewModel that exposes a Customer object from the model; an example of a one-to-many relationship may be a ViewModel that needs to expose an Order that contains a Customer along with multiple Products.  How these are exposed (as single or composite objects) is dependent on the needs of the application.  The ViewModel should depend on the Model for business logic (for example, calling to the Model to determine whether an object is editable based on the object's data values).

The ViewModel does not have direct knowledge of the View -- meaning, the ViewModel should not reference any of the controls or UI elements that are part of the View.  It can contain Presentation Logic (for example, exposing and setting properties that determine whether controls are shown or hidden), but it should leave it up to the View to determine how the elements are actually presented.

The Model does not have direct knowledge of the ViewModel or the View.  It is up to the ViewModel to handle any interaction with the Model (never the other way around).  The Model should contain the Business Logic, but the Presentation Logic should be limited to the ViewModel.

Example: Property Interaction
Let's take a look at a specific business rule that affects our user interface and see which components have the responsibility along the way.  To go back to our Order example, let's say that the Order cannot be changed after it has shipped.  The Model would contain the business logic to determine whether the Order has been shipped (perhaps by checking a ShippingDate field) and then set a ReadOnly property on the Order object appropriately.  The ViewModel would take this ReadOnly property and expose it to the View.  The View could then determine how to use this property through data binding.  For example, the View may have the IsReadOnly property on a set of TextBoxes data bound to the ViewModel property, or it may completely change the visual elements by showing TextBlocks if the ReadOnly property on the ViewModel is set to true.  The important part to remember is that the Model is responsible for the business logic (determining whether the Order is changeable), the ViewModel is responsible for exposing this property to the View, and the View is responsible for using the property to control the actual UI elements.

Example: Method Interaction
Now, a different perspective: let's say we have a Save button in our View, and we need to save the current object on the screen.  Note: there are several ways of implementing this; this just shows one way.  In our View, we have a Button with its Command property data bound to a SaveOrderCommand in the ViewModel.  In the ViewModel, the SaveOrderCommand object executes, which calls the Repository<Order>.Save() method (in the Model) and passes in the current Order object.  In the Model, the Save method in the repository performs the appropriate action, such as saving the Order to the database.  Note the interaction: the View only calls into the ViewModel, and it is up to the ViewModel to call into the Model.  Then the Model does the actual work.

MVVM: Problem Space
Now that we've seen the various components of the MVVM pattern, let's take a look at why we would want to use the pattern. At its core, the pattern addresses three main problem spaces:

Problem Space: Mixture of Presentation and Business Logic
Application developers often mix Presentation Logic code and Business Logic code together.  It's just too easy to do this with our modern tools: just open a new WPF project in Visual Studio, drag-and-drop some controls on to the XAML workspace, flip over to the code-behind and start slapping code together.  But coding this way leads to a maintenance nightmare.

Solution: MVVM encourages good separation of Presentation and Business Logic. With clearly defined components, the developer has appropriate places to put the presentation logic (the ViewModel) separate from the business logic (the Model).

A small caveat: notice that I used the word "encourages".  There is nothing in the pattern (or any pattern) that forces you to put code in one place or another.  Once we start to put code in the wrong area, we end up breaking the pattern, but our code might still work.  We need to be attentive that we are actually putting the code in the appropriate area.  If we start to break the pattern, then we will lose the benefits.

Problem Space: Unit Testing of the Presentation Layer is Difficult
When we are unit testing (which should be always), our goal is to have tests that cover as much of our code as possible -- this includes the Presentation functionality.  When developing unit tests against a traditional UI (event handlers in the code-behind), it is difficult to split out individual functionality.  For example, if we want to unit test a Button's click event, we can create a unit test around the event handler itself.  But in the set up for the test, we will need to instantiate a Button object (the "sender" parameter) by using a fake or a mock.  This may also mean that we need to instantiate an entire UserControl object as a parent for the Button in order to get a valid test.

Solution: The ViewModel in MVVM lends itself to cleaner unit testing.  Using the example above, let's say that instead of the Button click event performing an action directly, it calls a method in the ViewModel.  Now, we can easily unit test the method in the ViewModel.  Since the ViewModel does not have reference to UI elements, we would not need to instantiate them for the unit test. This leads to code that is easier to test and is easier to isolate. Note: method calls will generally travel from the ViewModel to the Model, but because we have these "seams" in our application, it is easier to fake or mock those interactions in our unit tests.

Problem Space: File Sharing Between Designers and Developers
In situations where there are dedicated interaction designers and application developers, it can be difficult to coordinate work since the designers and developers need to interact with the same set of source files (for example, the MainPage.xaml and MainPage.xaml.cs files that travel together in source control).  This can get especially tricky when both areas need to check in changes to the same files at the same time.  In addition, the interaction designers need a certain amount of knowledge of the development environment so that they do not inadvertently break the developer's code.

Solution: With the physical separation of the View and ViewModel in MVVM, designers and developers can work more independently and safely.  The designers are only working with the View (XAML), and the developers are only working with the ViewModel and Model which are separate code files (.cs or .vb).  If the code-behind the XAML is eliminated (or at least minimized), then there is less risk that a designer could accidentally break some developer code.

This does not mean that the designers and developers work in isolation.  They still need constant communication.  What the designer can do with the UI is dependent upon the properties and methods that are exposed by the developers.  Collaboration is still vitally important, but MVVM will minimize the likelihood that they will need to edit the same source files at the same time.

One small caveat: in many of the development shops that we work in, there is no separate designer; we are both the designer and developer.  But even if we are not able to take advantage of this particular solution, we can still get the advantages of the clear separation of concerns and ability to unit test the presentation layer.

MVVM: Consequences
Every Design Pattern has both benefits and costs.  The MVVM pattern is no different.

Consequence: Added Complexity
MVVM adds complexity to the Presentation Layer of the application.  This is an additional learning curve for the development team.

When given a choice between dumbing-down code or smartening-up developers, I will choose the latter.  I always prefer to bring up the skill set of the development team.  But there may be some scenarios where this is not possible due to time constraints (ever heard this one before?).  We need to make sure that the developers on the team understand the pattern before we start using it extensively; otherwise, we may find folks who take short cuts to get things to work and end up breaking the pattern.

Consequence: Errors Move from Compile Time to Run Time
As we've seen, implementation of MVVM is made possible through the very flexible data binding that is available in the XAML world.  One of the downsides is that incorrect data binding will not generate errors at compile time.  These errors are moved to run time, and often the errors produce silent failures (simply an empty TextBox or other unexpected behavior).  Unfortunately, unit testing will most likely not catch these errors either since we are testing our ViewModel and not the View (where the bindings are specified).

These can be difficult to debug.  The best tip that I have is to make sure you have the Output window open in Visual Studio when debugging your application.  If there is a failed data binding, it will show up in the Output window.

Weighing the Costs
What is important is that we understand the costs and determine that we are willing to accept those costs in order to receive the benefits.  If we are aware of the negative consequences of the pattern, then we can take steps to mitigate them.  Just like every other tool in the toolbox, we need to make sure that we are picking the right one for the job.  If we are not getting the benefits of the pattern, then we are only getting the costs, and we should reconsider our approach.

What About Implementation?
We'll need to save implementation for another day.  As we noted earlier, there are a number of frameworks that can assist us.

Microsoft Patterns & Practices offers Prism as guidance for creating XAML-based (WPF, Silverlight, Windows Phone) applications.  This includes using MVVM for the presentation layer.  Prism provides a number of classes and interfaces that help make the implementation of MVVM cleaner and more generic.  This results in less boiler-plate and replicated code in the application.  Of course, it is always possible to implement these abstractions and helpers yourself, but someone else has already done the hard work.  There is also great documentation available, including Implementing the MVVM Pattern.

Another popular option is the MVVM Lite Toolkit.  This toolkit puts an emphasis on what they call "blendability" -- the ability to open and edit the user interface in Expression Blend.

Paul Sheriff shows the MVVM pattern in action without using external frameworks: The Basics of MVVM.  This has advantages of focusing on the pattern rather than the framework (as was mentioned earlier).  But there are some things that are a bit harder to do.  I've done some implementations using a similar method, and there are pros and cons as with everything else.

And there are plenty of other implementations as well.  If we go back to our Christopher Alexander quote above, patterns describe a solution "in such a way that you can use this solution a million times over, without ever doing it the same way twice."  This doesn't mean that we should re-invent the wheel; it just means that there are different types of wheels to choose from.

Wrap Up
MVVM is a very important pattern in the XAML world.  Much of the samples and guidance revolving around the latest implementations (Windows Phone 7 and Windows 8) use MVVM as the core presentation pattern.  What is important is that we understand the pattern itself, the components that make up the solution, and why we are using the pattern.  Once we have these things down, we can make better decisions when we are implementing MVVM in our own applications.  And when we are using an MVVM framework, we have a strong foundation to ensure that we are using the framework appropriately and that we are adhering to the principles of the pattern itself.

I am currently working on an application that shows a simple implementation of MVVM.  That code will be available in the near future.

Happy Coding!

Saturday, April 14, 2012

XAML App Review - Part 5: MVVM and Wrap Up

This is a continuation of the XAML App Review. The articles in this series are collected together here: Jeremy Bytes - Downloads.

Last time, we saw the Please Wait screen which turns asynchronous calls into synchronous application behavior.  This time, we'll take a look at the MVVM pattern and how it relates to our sample application.

The Model-View-ViewModel (MVVM) Pattern
As you've probably noticed, the XAML Tips application does not use the Model-View-ViewModel (MVVM) pattern.  We won't go in depth on the pattern (we'll save that for another day).  We'll just take a look at some basics, the the reasons for using the pattern, and why we did not use the pattern here.

First the basics: MVVM is a design pattern that is concerned with the presentation layer of the application.  As noted by the name, it consists of 3 parts.  The Model consists of the business layer of the application (and everything below that).  We can think of this as everything except for the presentation.  The View consists of the UI elements (the XAML) that the users sees and interacts with.  The ViewModel is the goo that holds the Model and View together.  It takes advantage of the flexible databinding model that is available in the XAML world.  Basically, the XAML elements are databound to properties and objects in the ViewModel (the View never directly interacts with the Model).  The ViewModel handles the communication with the Model to populate these objects and to make method calls through to the Model.

Now that we have seen the parts of the MVVM pattern, let's take a look at why we would want to use the pattern.  The benefits of the pattern are to resolve 3 main problem spaces:
  • Problem Space: Mixture of Presentation and Business Logic
    MVVM encourages good separation between the presentation and business layers of the application.
  • Problem Space: Unit Testing of the Presentation Layer is Difficult
    MVVM makes it easier to unit test the presentation layer by separating the UI elements (the View) from the presentation functionality (the ViewModel).
  • Problem Space: File Sharing between Designers and Developers
    MVVM makes it easier to manage source code because the designers can be working with the XAML files (the View) while the developers work with the code files (the ViewModel and Model).
All design patterns have both benefits and costs.  There are 2 primary costs of the MVVM pattern:
  • Cost: Added Complexity
    MVVM adds complexity to the presentation layer that requires an additional learning curve by the development team.
  • Cost: Errors Move from Compile Time to Run Time
    MVVM works through the flexible databinding mechanism in Silverlight/XAML.  Incorrect databinding does not cause compile-time errors, so a number of errors are moved to run time.
Again, this is just a quick overview of MVVM.  MVVM is a very important and useful pattern in the XAML world.  We'll take an in-depth look at this pattern in a future article.

Why No MVVM in XAML Tips?
There are a couple of reasons why the MVVM pattern was not used in the XAML Tips application (or more correctly, in the application that XAML Tips is based on).

First, the application would not take advantage of the benefits of the pattern.  Let's take a look at each of the benefits:
  • Mixture of Presentation and Business Logic
    As mentioned in the Introduction, we had been using CSLA as a business layer framework in other applications.  Because of this, we already had the separation of concerns between the UI and business layer.  As such, we already had a resolution for this problem space.  Note: CSLA is MVVM compatible (it really deals with the "M" part of the pattern), and there are helper objects to make working with the pattern easier.
  • Unit Testing of the Presentation Layer is Difficult
    At the time the application was written, we were not making extensive use of unit testing.  The testing that we did have was focused on the business layer.  In addition, the UI for this application was fairly simple (primarily CRUD operations).  As such, we were not doing unit testing of the presentation layer.
  • File Sharing between Designers and Developers
    For this application, the designer and developer were the same person (me).  As such, we would not get the benefit of the separation of the XAML and code files.
Second, as noted in the Introduction, this application was a first Silverlight production application.  We were trying to limit the number of new/unknown parts to the development.  Since we did not fully understand the environment we were working in, it would be difficult to correctly implement the MVVM pattern.  We would most likely have had several design issues and/or kludges to get things to work as expected.  Now that we have the basics under our belt, we are better equipped to understand what a good implementation of MVVM would look like.

MVVM is a Good Pattern
It's hard to do any work in the XAML world without running across the MVVM pattern.  It is a good pattern, and I recommend its use.  But as with all patterns, there are benefits and costs.  We should make sure that the benefits outweigh the costs in our implementation.

If I were to re-write this application, I would most likely use MVVM.  We could take advantage of the pattern to abstract some items (such as our Please Wait functionality) and to use databinding more extensively.

The Good, the Bad, and the Ugly
We've taken a look at a lot of different parts of our XAML Tips UI implementation.  Some things we like, some things need some changes, and some things need complete re-writes.  Here's where we ended up:

Overall Operation
The application behaves like a WinForms application (which is not necessarily bad).  But we can be more creative with our presentation based on the flexibility that XAML offers us.

Look and Feel
Having the style and brush resources centralized in the App.xaml is good.  This allows us to change the overall look of the application by making just a few changes.  The gradient design looks dated; we should look at updating the colors and styles to match current design sensibilities.

ICloseQueryable
The ICloseQueryable interface may be better served with a base class that exposes a Closing event.  Alternately, we could add an auto-save functionality that would make this unnecessary.

Form Manager
The form manager needs some better error handling in managing which form is docked in the client area (adding and removing the children from the UI element).  Also, we can look at a filmstrip-type interface that would change the way that the user interacts with multiple forms.

Popup Message
The popup message is a good implementation.  We can make this a little more visually interesting by changing the animation to behave more like "toast".

Please Wait Screen
There are too many problems with the Please Wait screen to use it as-is.  The risk is that the entire application will be locked up if the screen is not hidden appropriately.

MVVM
While the application did not use the MVVM pattern for the reasons stated above, we should reconsider this (based on being comfortable with the environment and understanding the pattern).  The ViewModel could be used to enhance the operation of the form controller, the popup message, and (most importantly), the Please Wait functionality.

Wrap Up
There were quite a few decisions made when this application was originally created.  Some of those decisions have stood up to the test of time, and some of those decisions have not.  The important part is that we take the time to go back to applications that we've created and take a look at them with a critical eye.  By reviewing what we did, we can pick out the parts that are good, the parts that need some improvement, and the parts that really need to be thrown out.

Our creations are never perfect.  And that's okay.  As long as we can admit that things can be done better, we can learn from our experience and move on.  If we ever think that an application is perfect (and refuse to budge from that view), then we've just slipped into the mode of being stuck in our ways.

Application development is about continuous learning ("development", if you will).  Let's keep learning and keep moving forward.

Happy Coding!