Showing posts with label Data Template. Show all posts
Showing posts with label Data Template. Show all posts

Sunday, July 8, 2012

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!

Monday, May 31, 2010

Updated Sessions

I have updated a number of my sessions for Visual Studio 2010 and/or Silverlight 4.  I will be presenting three of these sessions at the So Cal Code Camp coming up on June 26 & 27, 2010.  These are all available for download here: http://www.jeremybytes.com/demos.aspx.

Introduction to the BackgroundWorker Component with WPF
Long running processes are a user experience killer. How many times have you had an application "lock up" while trying to do some function? The BackgroundWorker component in .NET allows you to spawn those long running processes in the background and keep your WPF, Silverlight, or WinForms user interface responsive. We'll take a look at the features of the BackgroundWorker in a WPF application including running a background process, updating the progress in the UI, and cancelling the process before it has completed.

This session has been expanded to include Exception Handling and additional error checking.

Walkthrough: BackgroundWorker-WPF2010.pdf
Sample Code: BackgroundWorker-WPF2010.zip

Introduction to Data Templates and Value Converters in Silverlight
Business applications are all about data, and laying out that data is critical to creating a good user experience. Silverlight has several tools, including Data Templates and Value Converters, that make this easier for the business developer to manage. By the time we're done, you will have a good understanding of the basics of both of these valuable tools.

This session has been updated for Silverlight 4.

Walkthrough: DataTemplatesAndConverters2010.pdf
Sample Code: DataTemplatesAndConverters2010.zip

Introduction to XAML - WPF 2010 / Silverlight 4
Understanding XAML (eXtensible Application Markup Language) is a key to creating the latest .NET user experiences in WPF and Silverlight. We will introduce the basic concepts around XAML and take a look at various features such as namespaces, elements, properties, events, attached properties and some basic layout. We’ll create a simple WPF or Silverlight application that covers these fundamentals. Although you will probably end up doing most of your UI design with a drag-and-drop tool such as Expression Blend, knowing the internals gives you a leg up in making the final tweaks to ensure an excellent user experience.

This session has been updated to include both WPF and Silverlight versions.  The same core XAML features are covered in each environment.

Walkthrough (WPF): IntroToXAML-WPF2010.pdf
Sample Code (WPF): IntroToXAML-WPF2010.zip

Walkthrough (Silverlight): IntroToXAML-Silverlight4.pdf
Sample Code (Silverlight): IntroToXAML-Silverlight4.zip

As always, your feedback/questions on any of these sessions is appreciated: feedback@jeremybytes.com.

Happy Coding!

Monday, January 4, 2010

Introduction to Data Templates and Value Converters in Silverlight 3

(Editor's note: I will be presenting this topic at the SoCal Code Camp Jan 30 & 31, 2010.)

Overview
Business applications are all about data, and laying out that data is critical to creating a good user experience. Fortunately, Silverlight 3 has several tools, including Data Templates and Value Converters, that make this easier for the business application developer to manage. Today, we'll take a look at consuming a WCF service and creating the layout of the data. By the time we're done, you should have a good understanding of the basics of Data Templates and Value Converters.

Get It Here
As mentioned in a previous post, the demos are now available in PDF form here: http://www.jeremybytes.com/Demos.aspx.

Here's some direct links:
PDF Walkthough
Code Download

Happy coding!