In a prior installment of this series of articles about CODE Framework (“CODE Framework: Writing MVVM/MVC WPF Applications”, Jan/Feb 2012), I discussed how to use the WPF features of CODE Framework to create rich client applications in a highly productive and structured fashion reminiscent of creating ASP.NET MVC applications, although with WPF MVVM concepts applied. In this article, I will dive deeper into the subject and discuss the unique benefits of the CODE Framework WPF components which enable developers to create the part of the UI that is actually visible in a highly productive and reusable manner.
Most MVVM frameworks create great structure in setting up the overall infrastructure, but provide little in the way of actual UI development. “And here is where you create a user control that acts as the view…” is how the story usually goes and the developer is completely on her own in doing so. Not so in CODE Framework! Developers and designers alike can use many of the great (yet optional) features of the framework to quickly create great looking and completely stylable UIs. In fact, many of these features can be used even if your overall development framework is something else. You can simply bring these components into other setups as needed.
Getting Started
When you create CODE Framework WPF applications, you can use as little or as much as the UI-specific features as you like. Just like in any other framework, you can create your view as a user control (or similar UI element) in a XAML file with a C# or VB code-behind file. Or, you can go all out and use the CODE Framework “View” UI element and go cold turkey without even a code-behind file (which has great advantages as I will discuss as this article goes on). Or, you can simply use some of the convenient little features that might make general WPF development more straightforward and ease into the subject that way. Or you can mix and match any and all of those approaches. (NOTE: You can also create entire custom themes, which is not nearly as hard as it sounds, but that shall perhaps be the topic of a future article.)
“Most WPF/XAML MVVM Frameworks provide great structure for the mechanics of the UI but not for the things you actually see. CODE Framework is different.”
Let’s start out with a few very simple examples (and for those of you who are looking for the mind-blowing features… bear with me… we are getting there!). Let’s say you have a very simple UI, such as one based on a user control, perhaps one that creates a login UI with the option to enter a user name and password. Perhaps for that purpose, you arranged your user control into logical rows and columns using a Grid layout element. Something like the XAML shown in Listing 1 perhaps, which creates the UI shown in Figure 1.
For those of you familiar with any of the XAML dialects, this type of UI definition is probably well-known to you. There are quite a few things that bug me about this setup, however, ranging from little annoyances to the fact that with the proper techniques, this same UI can probably be defined in just a handful of lines of code. Let’s start out with the little things.
“Many CODE Framework features can be used individually and in combination with completely different frameworks.”
First, let’s talk about the definition of the Grid. It is very convenient to arrange UIs using Grid elements. What is not so convenient is that the syntax for the definition of Grid rows and columns tends to be rather verbose. In fact, looking at Listing 1, you will notice that almost half the required code (13 lines in this example) went towards row and column definitions. And sometimes you really want to do fancy things with all the various settings you can put on rows and columns, but in the majority of scenarios I ever see, people only set row heights and column widths. For this reason, CODE Framework provides a more convenient way to define rows and columns in a Grid. To take advantage of this feature, make sure you have a reference to Code.Framework.Wpf.dll in your project (see sidebar for how to get CODE Framework if you do not have it already). Also, define the namespace for CODE Framework WPF controls at the top of your UI like this (all in one line):
xmlns:c="clr-namespace:CODE.Framework.Wpf.Controls;
assembly=CODE.Framework.Wpf"
NOTE: If you are using a productivity tool such as Resharper, the tool will probably just add this line for you. Also, see the sidebar about XAML namespaces if you are not familiar with this feature.
Now that you have access to CODE Framework features in our UI, you can turn the 13-line Grid definition into the following:
<Grid c:GridEx.RowHeights="Auto,Auto,Auto,Auto,25,Auto"
c:GridEx.ColumnWidths="*,*">
The result of this is exactly the same as the 13-liner, except it is more convenient. Note that this is not just more convenient for direct declaration of row heights and column widths, but it also makes it much easier to style the control. For instance, you could create a control style with the exact same settings like this:
<Style TargetType="Grid" x:Key="MyStyle">
<Setter Property="c:GridEx.ColumnWidths"
Value="*,*" />
<Setter Property="c:GridEx.RowHeights"
Value="Auto,Auto,Auto,Auto,25,Auto" />
</Style>
This is much easier than it would be without this nifty feature! Note that we didn’t even have to use a special control. We still use a standard Grid, but the framework allows us to set RowHeights and ColumnWidths properties by means of attached properties. (If you are not familiar with attached properties, see the sidebar.) You could also use the GridEx element directly instead of a Grid and get a few more features yet, but in many cases, you will simply find yourself using a few attached properties in addition to what you are already doing.
This is a pattern you will see quite a few times in CODE Framework. In addition to the elements and controls you are already used to, there often is a control with almost the same name except for an “Ex” suffix that provides extended functionality. You can generally use either the “Ex” control, or just some attached properties provided by that class.
Another aspect that currently bugs me about this UI definition is the hardcoded width of the text elements. They are set to a width of 250 pixels. This may work fine for the current font settings, but what if someone changed the font, perhaps by changing the application’s overall style, or by setting Windows system settings, or anything like that. In that case, you may not like the width of 250 pixels anymore, because the font may either be too large or too small to accommodate as much information as you want.
A better way to set the width is to set the width to something that logically maps to about the same amount of text being visible regardless of font. (With proportional fonts, this is always a somewhat inexact science as you are dependent on which exact letters are being typed. But I want this to make some common sense once the UI pops up on the screen). Using the CODE Framework, I’ll show you how to set another attached property. This time, the property is defined on an element called “View”, which is part of the Code.Framework.Wpf.Mvvm.dll, so make sure you add that to your project references and make it accessible through a new namespace in your UI:
xmlns:m="clr-namespace:CODE.Framework.Wpf.Mvvm;
assembly=CODE.Framework.Wpf.Mvvm"
Again, this should be just one line without spaces in your code, even though the way this long line displays in the magazine is in two separate lines.
With that reference in your project, you can remove the “Width” setting from the two input controls and replace it with this:
m:View.WidthEx="25"
Note that the code changes from “250” to “25” as the value. The idea here is to say “I want a width that accommodates about 25 characters using the current font face and size, and assuming an average character width”. You can try to experiment with font settings and run your app (sometimes this doesn’t show up right away in the designer) to see how the width changes.
Note that you could set this attached property on both the textbox and the password-box. In fact, you can set the “WidthEx” property on any UI element. It is a very generic setting in that sense. That is why it is defined on the “View” object. You simply needed a generic place to put this sort of setting, and the View object seemed to make the most sense for that.
There is one final example of a convenience feature I want to add to the UI. You may notice that the textbox is bound to a value (which presumably will be provided by some sort of view model or whatever else you have set as the data context). This is a very convenient setup and typical for an MVVM application. Note that the password-box, on the other hand, does not have a binding, because the text of a password-box simply isn’t bindable in WPF. This is very inconvenient in an MVVM world, where you really want to bind just about anything to the view model. For this reason, we added the ability to bind a password-box by adding - you guessed it - an attached property that can be used like so right within the existing password-box:
c:PasswordBoxEx.Value="{Binding Password}"
There you are, with a fully bindable password-box!
You’ll find quite a few more of these convenience features in CODE Framework. These features range from simple visual aspects to code readability and productivity features (such as the Grid row and column definitions) to functional aspects (such as a bindable password box) to behavioral features such as allowing controls like ListBoxes and trees to be bound to meaningful WPF commands. The space I have in this article is too short to discuss them all, but I encourage you to explore some of these features on your own. Plus, we are adding new ones all the time!
Another aspect of all this that is really important is that so far, we are still dealing with a rather simple user control that has little to do with the CODE Framework, other than us having brought in a few DLLs and then having used some very specific features. You can use those features in any WPF application, regardless of whether CODE Framework is a key part of your setup or not. You can pick and choose not just the DLLs and classes you want to use, but in some cases, you may only want to use a single attached property. The level of choice you have is quite granular, and that is a deliberate design feature of CODE Framework.
Taking Things Further
You’ve now got your feet wet and have used some very simple features of the framework. You can make your entire login UI screen definition much simpler by taking things to the next step. To do so, change the root element of the UI from UserControl to the View element provided by CODE Framework:
<m:View x:Class="UITest.LoginControl" ...
NOTE: Since this UI has a code-behind file, you also need to go to that file and change the inheritance structure to inherit from View rather than user control, otherwise you’ll get a “can’t redefine baseclass…” error.
You can think of a View as a generic and extremely flexible container for UI definitions. By default, you can think of a View as a Grid, although you can change that layout behavior to your liking (which is often done in styles). Since the View itself can act as a Grid, you do not need the Grid definition anymore, so you can remove that completely. In fact, you can remove a whole lot more, including the Grid.Column and Grid.Row as well as the Grid.ColumnSpan settings. The View has the ability to figure that stuff out on its own. To do so, it uses advanced layout styling. (To follow along with this example, remove all such layout information from your UI definition now.)
NOTE: Layout styling is a subject all on its own, and I have, in fact, written an article about layout styling called “Super Productivity: Using WPF and Silverlight’s Automatic Layout Features in Business Applications”, which appeared in the 2010 Nov/Dec issue of CODE Magazine. It has nothing to do with CODE Framework as such, but explains the concepts CODE Framework uses in general terms.
By default, the View uses a Grid as its layout strategy. Since you removed all layout information from the UI definition, the layout will now look exactly like it would in any WPF Grid: All the controls are piled on top of one another. Not exactly useful or what you want. To create a more useful layout, we can use a different style. One such style that is available in all CODE Framework themes/skins is called CODE.Framework-Layout-SimpleFormLayout. What does this style look like? Well, that depends on which theme you are using. Suppose you choose one of the CODE Framework standard themes, such as “Metro” or “Battleship” (Windows 95 look); it will create a vertical stack of controls. Take a look at the UI definition in Listing 2, which as you can see, is significantly simpler than the one in Listing 1. Nevertheless, the result still looks the same as the UI in Figure 1.
NOTE: If you have created your project from scratch or aren’t using CODE Framework as your main framework, you need to make sure you add the desired theme DLL and merge in the “theme root” into your resources. (Using the CODE Framework templates, this is done automatically.) Assuming you want to use the Metro theme, add a reference to Code.Framework.Wpf.Theme.Metro.dll and add the following XAML to your App.xaml file to make sure the resource dictionaries that make up the Metro theme are available to your UI:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="pack://application:,,,
/CODE.Framework.Wpf.Theme.Metro;
component/ThemeRoot.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
When I first show developers a UI definition as the one in Listing 2, I generally make a point to draw their attention not to what’s there but to what isn’t there: a complete lack of any layout information. The listing defines only which controls we want and what they are bound to, and perhaps a few other “business things” such as the rough desired width of a control in a generic fashion. But the fact that you have a label at the top of the form, then a textbox a few pixels below, and so forth, is something that is completely driven by the style. And as such, it is also changeable by means of a style, so you could make it look completely different in the same Windows app, or you could even take this to different platforms such as Metro or Windows Phone, and have the style create an appropriate look for each specific platform.
Note that the UI is not just a simple top-to-bottom stack, but the two buttons at the bottom are supposed to be at the same level horizontally. Since the style doesn’t do that automatically, I added a StackPanel that handles these two buttons and let the style align the StackPanel as a whole. This is a fairly common thing to do. You may often have UIs you can have almost laid out entirely by some available style, except for one detail like these buttons. That doesn’t mean you can’t use the style. You simply use the style for what it does well and handle the rest (often the more interesting things) yourself. Composing UIs out of these different approaches is an important aspect.
So now you might wonder how you would know about the available styles. The simplest answer to that question is to use the CODE Framework Visual Studio Extensions (downloadable through the Extensions Manager in Visual Studio). This gives you CODE Framework-specific project templates, including one for Views. When you use that project template, a dialog pops up which lets you select the style for your view from a list (which is ever growing). This is a simple way to experiment with the different layout styles. Of course, you can also look into individual CODE Framework theme source code projects (they all start with “CODE.FrameworkWpf.Theme…” and see which XAML resources are there. The layout ones all have names that start with “[Theme]-Layout-…”, such as Metro-Layout-SimpleForm.xaml. We even make all these resource dictionaries available as a separate download for easy viewing of the WPF styles.
At this point you might wonder what the layout style you just used is defined as. You can see that code here:
<Style TargetType="ItemsControl"
x:Key="CODE.Framework-Layout-SimpleFormLayout">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Layout:BidirectionalStackPanel
ChildItemMargin="0,0,0,5" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
This is really just a lengthy way of saying “we want to use a BidirectionalStackPanel to lay out items in an ItemsControl”. The View object is an ItemsControl, so this style can be applied to it (but also to any other ItemsControl whether it is part of CODE Framework or not… again, you may see a design and philosophical pattern emerge here).
You might ask, what is a “bidirectional stack panel?” Well, it’s another one of those little convenience controls. It works much like a StackPanel in WPF, except for a few minor details. For one, it can stack things “both ways.” In other words: If you use a bidirectional stack panel with vertical orientation (the default), then controls are put into the stack one after the other from top to bottom. Except for those controls that have their individual vertical orientation set to “Bottom”, which are put in from the bottom up. In addition, this control allows setting the margin between the child items. (In this example, we set it so every control has a 5-pixel bottom margin.) In fact, this stack panel even has a special option for label and textbox type of controls, because we often have UIs that have alternating label/control patterns, where the label goes with the control (such as the “Username:” label before the username textbox and so on), and one usually wants a little less margin after the label.
If you run our example UI, you can see the bidirectional stack panel in action. Try to resize the login window and you will see that the login buttons always stick to the bottom of the window since they are defined in their own StackPanel which has its VerticalAlignment property set to Bottom.
A quick side-remark about the two buttons: The simplest way to define this UI would be to not have to define these two buttons at all. If you think about it from a slightly more abstract viewpoint, you will notice that the login form provides a few very simple aspects. You can enter the user name and password, and textbox controls are generally a good way to achieve that in just about any environment. The buttons then allow you to trigger or cancel login. But are buttons really the best approach for that? That depends on the exact environment and the applied theme. In a conventional Windows setup, buttons may be great. In a touch environment, perhaps you want a different kind of button, or perhaps you want to use gestures. On a phone or in Windows 8 Metro, you may use buttons that are integrated with the device. The list goes on and on, and the point I am making is that you really do not know whether buttons are the best way to go.
A better approach (which would also be more productive for developers) is to define that both the login and cancel actions are available but leave it up to the applied theme/skin to decide how to best present these standard actions. In the CODE Framework, that is possible through the Actions collection that can be (optionally) present on view models. The style then simply picks that up and shows it in the UI. If you create a default CODE Framework WPF MVVM/MVC app, you will see a login screen that looks suspiciously like the one we are creating in this article, including the two buttons, but they are only defined on the view model. For more information on this technique, see the CODE Framework MVVM/MVC article as well as the WPF Layout article (see above for both).
More Automatic Layout
The login form I’ve demonstrated so far is a very simple user interface. So let’s see if we can do something more exciting. Let’s create a customer edit form UI with the ability to search and add customers. To do this, I’ll walk you through creating a brand new CODE Framework WPF MVVM/MVC project. If you have never done that before, check out my article about building CODE Framework WPF MVVM/MVC apps (see above). The quick version of this relatively simple process is this: If you do not have CODE Framework installed, search for the CODE Framework Tools using the Visual Studio Extensions Manager (Tools menu). Then, create a new solution and pick the WPF MVVM/MVC project template. If you do not have the CODE Framework assemblies, the template will offer to download them automatically from CodePlex, which you should do. When you create the new project, pick the “Battleship” theme as your default theme to start out with (but choose to generally include both Battleship and Metro themes).
The first feature I’ll show you how to add to the new project is a customer list and search interface. To do so, add a new Controller to the Controllers folder and add a Search() method. Then, go to the existing StartViewModel and add an action to its list of standard actions (or use one of the dummy ones that is already there), and when executed, call Controller.Action(“Customer”, “Search”) to trigger the Search() method on the newly created controller. (NOTE: If you are not familiar with these steps but want to follow along, check out the previous CODE Framework WPF MVVM/MVC article… see above.) The detailed setup of the Controller and even the ViewModel do not matter for our purposes here. In this article we only care about the View. So let’s go ahead and add the new View in the Views/Customer folder (you will have to add the “Customer” sub-folder to your Views folder).
The ultimate goal is to create a user interface that looks like the UIs shown in Figure 3 and Figure 4 (which are the same UI but with different themes/skins applied). The search UI has two distinct parts: The “main” or “primary” part of the UI shows the list of customers as the result of the search, and the “secondary” part contains three textboxes that allow the user to specify search criteria. As it turns out, quite a few UIs follow this “primary/secondary” UI pattern, where a large area occupies the main part of the UI and a secondary part provides additional features. Think of Windows Explorer showing a list of files in the main area and a tree in the secondary area (possibly with the tree area hidden). Or think of many of the Office applications and how they can show optional panels attached to the side of a screen. I am sure you can think of many more such examples. Since this type of UI setup is so common, CODE Framework provides default styles for this known as the “Primary/Secondary Form Layout.” In fact, there are two slight variations on that theme. A general purpose style of that name as well as one that is specific for showing lists. UIs with lists in their main area tend to have a slightly different look than the ones that do not, so there are two options by default. For this example you want to use the one for lists.
To create a new view with this style, add a new item to the Views/Customer folder and pick the CODE Framework View template. This shows the dialog shown in Figure 2. Note that this dialog lets you pick the “Primary/Secondary” style as one of the default options, which puts you right where you want to be.
As the next step, we define the list part of the view (the part that will ultimately show the customer search results). For now, all we are going to do is put a ListBox in the view and bind it to a “Customers” collection on the view model. (I am skipping the details of the view model here, but you can download the companion source code for this article to see the details of the view model definition.) To indicate to the view that this is the control you want to use for the primary area of the UI, you can set the View.UIElementType attached property to “Primary”. And that’s about it for the core definition of the list. Observant readers may notice that I have not yet defined which fields I want to show in the list, how they are to be displayed, or anything of that nature. In fact, the list as it is defined right now will show an entry for each of the customers found, but it will show no actual field information, so the list is not very useful. However, we are not currently worried with that part, since each theme may want to show search results in a different way. So all I’ll do for now is define that the list is based on a style called “Customer-List” which I have yet to define. (See Listing 3 for the complete source of the view definition.)
The “secondary” part of the UI is going to host the search UI. The style I have chosen is going to do a good job out of the box at placing the secondary UI-part in an appropriate spot for each theme the user may choose. In fact, by default, this style is going to be somewhat intelligent and look at the dimensions of the secondary UI. If the secondary UI is tall and skinny, it will be put either to the right or the left of the main UI. If on the other hand, the secondary UI is very wide but not very tall, the style will put that UI either at the top or the bottom. At least that is what happens in most themes. Of course, you can completely change the way this works, and you can change other aspects, such as the threshold at which it flips from one approach to another, or whether you want that behavior at all. (Take a look at the GridPrimarySecondary class for a list of all the properties you can set.) Some themes may also choose a completely different approach. Perhaps on smaller screen sizes, a theme could decide to only show the primary UI and float in the secondary UI only when needed. There is no limit to the options you can pick here except your imagination and perhaps some UI standards you may want to follow.
What all this means is that you do not have to worry in general terms as to where the secondary UI is going to go. You only have to define it. But how do you define that UI exactly? After all, the “secondary UI” is really a collection of controls rather than just a single control. The answer is deceptively simple: You can simply put all of those controls into a container and then flag the container as the secondary UI. How the controls are laid out inside the container is a different matter. In the example you might want a layout you are already familiar with: The simple form layout with controls stacked top to bottom and some other controls stacked from the bottom up. To facilitate all this, you’ll use a View object as the container (yes, a View element inside another View… there is nothing wrong with that) and set the style to the familiar “simple form layout” style. And voila! The UI is done. Quick and painless, yet extremely flexible and reusable.
“Some UIs cannot be laid out entirely in a fully automatic fashion, but are compositions made out of smaller individual UI segments that use automatic layout features individually.”
What you’ve just done is an extremely important concept in the CODE Framework: You’ve used automatic layout features, but you aren’t using the automatic layout system to lay out the entire form all at once. I would consider it very unlikely that you have many forms in your application which could all be laid out in one swoop by a single generic layout mechanism. However, by composing individual parts of the UI from pieces that can individually be laid out automatically, you can probably handle a very wide range of UIs. There will likely still be a certain percentage of your UIs (or parts of those UIs) that you have to lay out by hand, and that is OK. Being able to use automatic layout for the rest of the views, however, provides huge advantages in terms of developer productivity and long term maintainability and reusability of your application. Understanding the ability to apply automatic layout features to sub-sections of your UIs is a big step towards becoming a super-productive WPF developer.
At this point, the example is still missing some functionality. You will want to launch a customer edit form when the user selects an item from the list (as well as when the “New Customer…” button is clicked). Let’s create some code that handles customer selections. Many developers would now create an event handler for events such as double-click in the code-behind file. Note, however, that our view doesn’t even have a code-behind file at all. What’s up with that? Well, for one, you can create regular views with code-behind files and use them in CODE Framework without problems if you wish to do so. (CODE Framework supports both compiled views - those with code-behind files - as well as loose XAML views that do not have any associated code-behind files). Personally, I really like views without code-behind files for a number of reasons. For one, they are more generic and can be reused in more different scenarios if they are not tied to a specific code-behind file and associated classes that may only be available in some XAML dialects. They are also not pre-compiled with a specific XAML dialect, which means that your application can do some pre-processing before loading the views. (For instance, there is no Label control in Silverlight, but the framework can handle that with a pre-processing step of a loose XAML file but not a compiled one). Also, developers tend to put way too much code into code-behind files, which causes bad implementations and views that aren’t very flexible or reusable. For instance, if you hook the ListBox’s double-click event, you would be forever trapped in having to use a double-click. But what if you want to run the view in a touch scenario? Then you’d only want to single-tap. Or perhaps you want to run the view on a phone and double-clicks may not apply there. Maybe you want to have a right-click option to trigger editing. And so on, and so on. By not providing a code-behind file to put inflexible code like this, developers are practically forced to write good code. (NOTE: You can always do the same thing you can do in code-behind files in behaviors. And if you really were to run into a scenario where this is not the case, first, please drop me an email, because I’d like to see this. Second, you could always use a code-behind file just for that view.)
The example for this article will simply use actions to drive customer editing. I have added a view action (command) called “EditCustomer” to the view model, and I can simply bind my ListBox to that action. As you may know, ListBoxes do not have a useful command setup for this purpose, so we added one in CODE Framework. Simply set ListBoxEx.Command and you are good to go. Better yet, ListBoxEx provides a few additional settings that specify whether commands are to be triggered on single click or double click. (Take a look at the downloadable source for details on that implementation.)
Note that this sort of setup is also somewhat common in the CODE Framework. Whenever functionality useful to MVVM-style architecture and general coding without code-behind is missing, we try to add it. However, we can’t possibly anticipate all scenarios developers may encounter and provide specific command bindings for them. Instead, we have a generic attached property on an object called “Ex” that provides an EventCommand property (as well as an EventCommands collection in case you need more than one), which allows binding any event to a command. For instance, if you wanted to bind a button’s double-click event to a command, you could do it in the following fashion:
<Button Content="Hello">
<c:Ex.EventCommand>
<c:EventCommand Command="{Binding DoubleClickCommand}"
Event="MouseDoubleClick" />
</c:Ex.EventCommand>
</Button>
Using Themes
So far, we have created a fully functional customer list with a severe lack of any real information. We can search for customers and we can see a list of customers, but the resulting list only shows the name of the bound class (“CustomerQuickInformation”) rather than useful data such as the customer’s name. What is missing is a data template for each item in the list.
Using standard WPF (or any or XAML dialect for that matter) technique, we can simply define an ItemTemplate for the ListBox to remedy the situation. However, if you were to do that right in the view definition, then the format of the list would now be hardcoded and couldn’t be changed specific to a certain theme or even a different platform such as a touch-enabled environment or a mobile device. A much better approach is to put the same definition into a resource dictionary (basically a separate XAML file). This is no more or less work than putting it directly into the view, so this is even a good idea if you never switch to a different theme or platform. Besides, you never know whether you may want to change to a different theme later. Chances are that 5 or 10 years down the road, you might want to create a face-lift for your application. (This also makes UI elements like item templates very nicely editable and designable with tools such as Expression Blend, which I highly recommend using.)
“Putting templates into theme-specific resources is no more or less work than putting them right into the view, which makes this a good idea even if you only plan to use a single theme. Not to mention that they work better with Expression Blend.”
The CODE Framework has the ability to automatically manage resource dictionaries for you. Every view you create can optionally have additional resource dictionaries associated by simple naming convention. Using standard CODE Framework templates, you can create such resource dictionaries automatically (depending on the options you pick in the dialog shown in Figure 2). Figure 5 shows the search view source file with the associated resource dictionaries.
The rules for loading resource dictionaries are simple. When loading a view (such as Search.xaml), the framework also searches for XAML files with a “.Layout.” infix. Therefore, the Search.xaml view will always also load Search.Layout.xaml (if it exists) without you having to manually add that dictionary or having to merge it in yourself. (In fact, you should never load these dictionaries manually to avoid having unwanted and confusing resources available in scenarios where they are not wanted.) You can add up to 20 layout resource dictionaries (such as “Search.Layout.xaml”, “Search.Layout.0.xaml”, “Search.Layout.1.xaml”, and so forth), which will all be loaded and provide a convenient place to put individual resources associated your view without having to create a single “monster” resource dictionary.
The CODE Framework also loads theme-specific (I am using the terms “theme” and “skin” interchangeably as is common in the developer community) resource dictionaries. CODE Framework WPF applications have a “global” setting for the current theme set on the Application object. The framework uses an ApplicationEx object which provides a Theme property. Based on this property, the framework loads different resources. For instance, if that property is set to “Metro” the “Search.Metro.xaml” resource is also loaded with the search view. If the theme was set to “Battleship” it would load “Search.Battleship.xaml” instead. This article isn’t about creating new themes (I will write a future article about that), but you can freely expand on the theming system in CODE Framework and create your own themes or customize existing ones. So assuming you had created a theme called “BlueOcean” (note that there can’t be spaces in theme names), the framework would try to load a file called “Search.BlueOcean.xaml”. In the example for this article, that file does not exist. Whenever that happens, the framework tries to load a default theme file, so it would load “Search.Default.xaml” if that file existed (as it does in the example for this artcicle). The default file is a good place to put catch-all resources, but note that it is only loaded if no specific file is found. It will not be loaded in addition to theme files as some people incorrectly believe. (You can, however, manually create additional resource dictionaries that do not follow any naming convention and are thus not automatically handled by the CODE Framework and add dictionary merge commands to the automatic dictionaries. This is great for creating and loading resources that are shared across theme-specific dictionaries. Among other scenarios, graphical assets such as icons may often be defined in this way.)
It is common to only create theme-specific files for a handful of themes but use the default file for all others. Maybe you support five different themes in your application, four of which are simply different font and color variations on a basic Windows theme while the fifth is a touch-specific option. You may create a default dictionary that is generally used and only create one additional one for the touch-specific setup.
Returning to the example at hand, let’s create a definition for the customer list for our simple Windows 95 style (called “Battleship”). As you can see in Listing 3, the ListBox is defined as using a style called “Customer-List”. We can thus put a style definition with that key into our Search.Battleship.xaml file. A basic setup of this style can look like this:
<Style x:Key="Customer-List" TargetType="ListBox"
BasedOn="{StaticResource {x:Type ListBox}}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<!-- and so on... -->
As you can see, this style is defined to be applicable for ListBox elements. It is also based on the default style for ListBoxes. Themes may choose to completely re-define the way certain controls look (ListBoxes in Metro, for instance, have a different appearance than they do in Windows 7). I don’t want to worry about what that specific look is, but I want to respect it. That is why I will base it on the default. In addition, I then define the ItemTemplate as a DataTemplate. The exact details are omitted from the code snippet above, but the basic idea is simple. The template of each item is a Grid which has several columns. Within the first column I place a rectangle with a data-bound fill color based on whether or not the customer is active. Columns 2 and 3 have data-bound text elements to show the customer’s name and company name. You can see the full code example in Listing 4.
Listing 4 has a few other details of interest. I want the ListBox to look like a data grid. For that purpose, I created a simple template for the entire ListBox that shows a header with labels for each column. I use a Grid to define this header element and I even allow for GridSplitter elements to resize some of the columns. The data template for each individual item defines the individual columns within each row (which are technically independent from every other row in the list) to have a width that is data-bound to the width of the header column. With that, I get a working “grid control” where each row shows its data in columns and those columns are resizable through the header as you would expect.
Listing 4 has one more interesting trick: As you may recall, the entire view uses a style called “CODE.Framework-Layout-ListPrimarySecondaryFormLayout”. This is a style defined by the framework we intended to use directly and our view was never designed to define a custom style for the layout. However, in this case (mainly to show this technique in this example), I decided to override that style anyway and create a style of the same name in the Battleship resource dictionary:
<Style TargetType="ItemsControl"
x:Key="CODE.Framework-Layout-
ListPrimarySecondaryFormLayout">
Since the resource dictionary specific to the view is loaded (internally) after the style of the same name provided by the framework, this style takes precedence and will be the one applied. (This is a standard XAML technique and useful for many things with or without CODE Framework.) The actual definition of this style is copied almost 1:1 from the default definition as found in the CODE Framework source (which is available to everyone). The only thing I changed is that I increased the SecondaryUIElementAlignmentChangeSize property to “500” indicating that I want my secondary UI to be aligned across the top of the view, unless it is taller than 500 pixels. (It isn’t in our example, thus effectively forcing the search UI to be positioned at the top of the screen.) Figure 3 shows the result.
Now, all the example lacks is a definition of a look specific to Metro. To achieve the appearance shown in Figure 4, I’ll follow the same steps as for the Battleship theme (except I won’t mess with the overall layout style this time). The ListBox’ item template now is a simple Grid of a size hardcoded to 75x250 pixels. Within it, I placed two data-bound text elements as well as an icon (which I downloaded as a XAML-based vector image from www.Xamalot.com - see sidebar). To create a nice multi-column flow of elements within the list, I styled the items panel of the ListBox to use a WrapPanel element. Furthermore, I want slightly different select-behavior. While in a “regular” Windows world, I would expect to double-click a customer to edit it; in Metro, I would expect to single-click (or single-tap in a touch environment) to achieve the same result. I can do this by adding the following to the definition of my ListBox style:
<Style TargetType="ListBox"
x:Key="Customer-List"
BasedOn="{StaticResource Metro-Control-ListBox}">
<Setter Property="c:ListBoxEx.CommandTrigger"
Value="Select" />
This is a small change, but it is also profound as it shows that one can use styles to not only change visual aspects such as colors or layout, but even drive behavior of a user interface. (If all this re-styling of ListBoxes is new to you, check out my article about styling ListBoxes in XAML. See sidebar for more details.)
Note how little effort actually went into creating these different themes, yet the results as shown in Figure 3 and Figure 4 are quite different in appearance and even behavior. Experiment with the application by running it with both themes. You can change themes directly in the App.xaml file, but you can also swap themes in the running application by using the menu items/tiles that are added for this purpose by default. Note that you can cause a style change any time you desire either by triggering a SwitchThemeViewAction as shown in the StartViewModel class, or by simply setting the Theme property of the current application:
var app = (App.Current as ApplicationEx);
app.Theme = "Blue";
This causes the current application to unload all theme-specific resources and load the ones for the specified theme instead (following the rules described above). This works even for UIs already loaded, which will completely change look and behavior on the fly when you do this. This effect often “blows developers away” as the results can be dramatic, yet are very simple to achieve. Switch back and forth between the Battleship and the Metro themes to experiment with this feature of the framework.
The View Visualizer
When it comes to working with all these resources, one of the advantages is that during development, each resource remains very simple and manageable. However, things can get a bit tricky once the application is running and you are trying to figure out what is going on. (NOTE: This is an issue for all XAML applications and not specific to CODE Framework.) To remedy this situation, CODE Framework provides a “View Visualizer”, which is a developer tool that is turned on by default in App.xaml.cs (yet should be turned off before you deploy your application).
The View Visualizer provides a list of all views currently running and shows details about which view and view model each UI is using. It also shows which controller has launched the UI, thus giving you all three pieces of information going along with MVC scenarios. This is a very valuable tool to have, especially when it comes to maintaining applications, or when you are asked to work on a UI that was originally created by a different developer and you may not know where to find all the pieces.
However, the View Visualizer provides a lot more detail about each individual view. Once you select a view from the list of open views, you can not only see a live and zoomable visual of the view (useful for taking a close look at view details), but you can also see a hierarchical display of all the elements that make up the view. (During development, we would refer to this as the “document outline”.) You can hover your mouse over each element in the view to see a preview of just that element (useful for identifying the specific element you are looking for in complex views) and you can then select an element to see additional details. Those details include a list of all resource dictionaries that are loaded and accessible to the selected element (which could be application-global, specific to the current view, or even specific to the current element) and all the resource dictionaries these dictionaries may be loading and so on (dictionary merging can cause large hierarchies to be loaded).
“The View Visualizer provides tools for WPF similar in concept to what Firebug in Firefox provides for HTML.”
In addition, you can choose to see all the styles and their individual settings that apply to the selected element. For those of you who have done web development and have used either the Internet Explorer Developer Tools or Firebug in Firefox, this is probably a familiar sight, as this part of the visualizer aims to provide the same information or its XAML equivalent. It allows you to easily see which styles are applied and why (they may be explicitly set by key or brought in implicitly based on the control type) and which styles these styles are based on, and so forth. You can also see which style settings have been overridden by subsequent styles as these settings are crossed out. Again, to web developers, this is probably a familiar sight, while a tool like this used to be sorely missing in WPF. Figure 6 shows the tool in action.
Editing Customers
At this point, the example is already quite interesting from a developer’s point of view. Nevertheless, I also want to create a customer edit form to show a few more details. Fundamentally, the provided example (as shown in Figure 7) is relatively simple, yet it has some very interesting details. Listing 5 shows the definition of this view (which is stored in only a single file with no needed additional resource dictionaries at all).
The most interesting aspect of the edit view definition is not what is there, but what is not there. If you look closely, you will see that in true CODE Framework fashion, the view definition is very simple and only lists the different elements you want in the UI, what they are bound to, and a few abstract layout hints, such as the width of the elements in a generic and style independent fashion as well as group and column breaks. And that’s it! The actual layout of this form is created by a style called “Edit Form Layout”, which produces the result shown in Figure 7.
In this example, the style was able to lay out the entire form all at once, allowing you to not just be super-productive in the creation of the form but also create a view that is highly reusable in other XAML dialects and even in completely different scenarios such as ASP.NET MVC, iOS and Android. Is it realistic in real-world scenarios to have UI definitions that can be completely handled by a style like this? Well, as it turns out, most business applications tend to have a number of trivial edit forms that can indeed be handled in this fashion. Most serious forms, however, are likely to be more complex. In those cases, it is more realistic to apply these automatic layout styles to sub-sections of the view (like we did with the search screen) and compose larger views out of smaller areas that are laid out automatically (or if need be, even manually).
Figure 8 shows the same view from Figure 7, but this time it runs on true Windows 8 using Windows 8 Metro (not to be confused with the Metro style which I applied to a Windows 7 WPF application throughout this article). While the view definition remains unchanged, the applied style chooses to present the view differently. Labels are now above their associated controls. Spacing is different. Font sizes are different. Yet using CODE Framework, we can still use the same exact view without changes. This not only saves a ton of work when moving to Metro, but it also allows you to reuse code that is already well tested.
Another example of reusing the same view is shown in Figure 9, which shows the view running on Windows Phone 7. These examples lead us beyond the focus of this article and into using different areas of the framework such as the Windows 8 and Windows Phone specific implementaitons (and more). I do not have the space in this article to talk about those aspects in detail (these may be the subject of future installments of this column), but it is important to understand and know that if you are defining your UIs using the techniques described here, you are not just going to be very productive in creating your UIs, but you will also have created much more reusable UIs in the long run.
Some Loose Ends
Is that all there is to know about UI development in WPF with the CODE Framework? Not by a long shot. But I hope to have given you a good overview of the most important aspects and the overall paradigm, which should allow you to explore further steps on your own. There are a few odds and ends that have not fit in well into the article to this point that I would still like to point out.
Fonts
One is the use of fonts and font sizes. All default CODE Framework themes define default settings for font families and font sizes. Those are usually defined within each theme’s resources (in the framework source code) in a file called Fonts.xaml. Most importantly, there is a resource called “DefaultFont” which is used to define the theme’s default font family. You should use that reference rather than explicitly setting the font on any of your elements:
<!-- Good -->
<TextBlock FontFamily="{DynamicResource DefaultFont}" />
<!-- Bad -->
<TextBlock FontFamily="Segoe UI" />
If you find yourself needing different font families in your app, simply add more resources in your own resource dictionaries. A simple way to do so is to create your own Fonts.xaml file in the Themes/[Name] folder, which the default CODE Framework template already created for you (for instance, if you chose to include the Metro theme, simply add a Themes/Metro/Fonts.xaml file). Add a link to your merged dictionary from the root theme file (such as Metro.xaml in case if the Metro theme), which will cause the framework to automatically load your font definition resource dictionary when that theme is applied.
Colors
A similar concept applies for colors. You should never apply a color explicitly, but you should always use styles for colors. This allows for much greater flexibility (not to mention consistency) across your application. It is not uncommon for applications to offer completely new “skins” using the simple trick of swapping the color dictionary. CODE Framework, by default, defines twelve different standard colors (three foreground, three background, three highlight, and three theme colors) all defined in the Colors.xaml file. Since WPF sometimes needs colors and sometimes needs brushes, there are brush-equivalents for all these colors as well. (If you want to make changes, you only need to change the colors as the brushes automatically use the colors to define themselves). You may have noticed that all the Metro examples in this article use a blue background while the default template creates a red background. I achieved this simply by putting the following setting into my Metro-Colors.xaml file in the Metro theme folder:
<Color x:Key="CODE.Framework-Application-
ThemeColor1">Navy</Color>
Again, add to the list of colors if needed (and it is generally a good idea to create color as well as brush resources), but do not use explicit colors in your views and view-specific styles.
Message Boxes
A final feature I want to point out is one that deals with the common need of message boxes. It is very tempting to simply put a call to MessageBox.Show() in your view model, but this kills reuse as well as other aspects such as testability. To avoid this problem, CODE Framework offers its own message box feature. To show a message box, simply use the Controller.Message() method:
Controller.Message("Pretending to save data...", "Saving");
Fundamentally, this call supports the same parameters you would expect on the standard Windows message box. In fact, many styles choose to use the default message box feature to enable controller messages. However, many styles choose to display messages completely different in a way that is appropriate for the style (see Figure 10). For testability, the framework also allows for mocking of chosen values in message boxes, so you can place a call to a message box and simulate the user picking one of the available options without ever having to display a UI.
CODE Framework message boxes also have quite a number of features that standard message boxes lack. As it turns out, CODE Framework message boxes are really just standardized UIs with a view definition and a view model. If you are placing a standard call to the Controller.Message() action, the framework automatically creates a standard view and view model appropriate to display message box. However, you can also add your own view and view model if you want. This allows much greater flexibility. For instance, you can easily create completely different captions for your buttons. Or, you could create complete custom views and models to add elements such as textboxes or drop down lists to your message boxes. Since this feature is using the standard view/view-model architecture of the framework, you could create UIs with no limit to complexity. (However, most message boxes should probably not have hundreds of UI elements in real world scenarios.)
Getting You Started
And there you have it! While this isn’t nearly all I would like to talk about, this should still give you an overview of the most important features and paradigms. For more information, download the example associated with this article and visit http://codemag.com/framework. Also, feel free to send me an email. I am always happy to help you out with CODE Framework questions. Furthermore, CODE is offering training classes for CODE Framework on a regular basis. Check out http://codemag.com/training for details. If you are interested in attending a class, contact the CODE training division at info@codemag.com and mention you read this article, which will give you a discount on attending the course.