devxlogo

Building Polished UIs with Expression Blend—Part 1

Building Polished UIs with Expression Blend—Part 1

ith WPF and Silverlight, Microsoft provides both Windows and Web developers with powerful technologies to create rich, professional, and exciting user experiences.

However, in general, developers aren’t graphical designers, leaving most developers wondering how to cope with this new world of designed interfaces and polished user experiences. But fear not! With Expression Blend, Microsoft provides a great tool to create such UIs, and even developers with no graphical talents whatsoever can learn a few techniques that will help them build better looking applications.

One amazing thing about WPF and Silverlight is the polarity in quality between applications. One demo at a keynote of a major event such as PDC will show some of the most amazing user interfaces ever conceived. But another session at the same event will show a technically sound presentation that looks like a three year old just slapped it together (no offense to any three year olds reading this article). You can see the same thing in production applications: You can find some polished applications while others come across as complete messes with awful artwork and intrusive animations that make you want to reach for sea-sickness medications.

The root problem is not unique to WPF and Silverlight, but it is shared by many powerful technologies: They enable an extremely wide range of possibilities, both positive and negative. It takes expert knowledge to fall on the desirable end of that range. WPF and Silverlight exacerbate the problem because they require both development and graphic skills?a combination of talents that’s hard to come by. The result is that people working with WPF/SL are developers who are now tasked with creating a beautiful and “exciting experience.” In the past, the typical developer skill set called for only functional things, and the term “experience” was called upon only when after users started to pound tables in frustration over a bug or missing feature.

So how can developers cope with this situation? One approach is to take art and design lessons?and that certainly wouldn’t hurt if you have interest and motivation. However, in this article I’ll show you a simpler way: I’ll teach you a few graphical tricks that require no real artistic talents. Almost like “paint by numbers,” really. Just as following recipes can make you a decent home chef, following some basic guidelines can help you create decent WPF/SL experiences. Over time you’ll create a collection of such tricks?a sort of cookbook for graphical WPF/SL home cooking. And for the more unusual things, you can always call in the designers.

An Example Application

To demonstrate a few of these points, the small (but realistic) example application for this article is a WPF interface for a real-life middle-tier application. You can apply these techniques to Silverlight as well.

Author’s Note: I picked WPF because I had to pick one of the two technologies to keep the example at a reasonable size. Note that the downloadable code sample for this article includes a scaled-down version of the middle tier to eliminate dependencies on real-life databases and frameworks. However, the example as described here was explicitly based on a real application to make sure it is representative.

The application uses the middle tier of team-management software that my company used on our upcoming JockTock product and web site, which assists with organizing hobby sports teams. This particular example revolves around ice hockey. The middle tier serves up lists of teams and player rosters for each team. The goal of this example application is to pick up that data in the WPF UI and display it in a professional manner that takes advantage of WPF features.

To start out, I created a WPF solution in Visual Studio (VS) 2008 using the .NET Framework, version 3.5. The solution includes only a simple main window that displays a list of teams. When a user clicks on one of the teams, the window displays all the players for that team. The existing middle tier provides all the logic, so I didn’t have to write much code; most of the work involves building the UI and its design using Microsoft Expression Blend. However, I generally like to start out setting up my WPF/SL projects and solutions from within Visual Studio as that seems to create better starting points for sophisticated applications. (Solutions created by Blend seem to be more geared towards graphical designs, rather than complete applications.)

So why even use Blend? Because it provides many graphical design features, from easy access to color palettes and gradients, to sophisticated features like animations and resources. These are features developers don’t necessarily have to worry about right away, but one can gradually explore and adopt more and more of these hidden treasures.

Also, Blend conveniently uses the identical project structure used by Visual Studio, so you can switch back and forth between Visual Studio and Blend seamlessly. That allowed me to write code in VS but do all the design work in Blend. Microsoft originally created Blend for designers, while VS had a minimal XAML editor for developers. However, I personally favor Blend for all WPF/SL UI editing, even though I am not even close to calling myself a designer. I simply find the Blend UI more productive for any UI editing task. (Your personal preference may vary.) For this reason I will use Blend for all UI editing tasks in this article. You can make some (but not all) of the required edits in the Visual Studio XAML designer. The techniques shown for the WPF application also apply for Silverlight.

At first sight, Blend looks quite a bit different from Visual Studio. The color scheme is completely different, and most developers aren’t accustomed to Blend’s black look, which is clearly geared more towards the designer audience.

Author’s Note: Some people say they have a hard time reading the black stuff. In that case, I recommend switching to the light skin that you’ll find in the Options.

However, Blend and Visual Studio aren’t that different after all. Most developers will use Blend’s solution explorer, which is quite similar to the one in Visual Studio. In addition, the property grid is available in both apps, with Blend’s version arguably being much more comfortable and easy to use. Blend also provides simple access to all objects in the hierarchy, a feature Visual Studio lacks (at least in a fashion that is as powerful and intuitive as Blend’s).

Editor’s Note: This article was first published in the March/April 2009 issue of CoDe Magazine, and is reprinted here by permission.

Creating the Application Basics

I want the example application to show two lists of data: a list of teams on the left that users can choose from, and the players for a selected team on the right. There are more players assigned to each team than there are teams, so I would the list of players should to take up more room than the list of teams, but users should to be able to resize both areas.

WPF provides a great way to create the basic mechanics for such a UI. When you adds a new window object using either Blend or Visual Studio, the created default includes a Grid layout element. Grids are very useful, but are also very confusingly named. Most developers think of “grids” as containers for lists of data organized in columns and rows. In WPF, a grid has nothing to do with displayed data; instead, a Grid is a layout element?a way of organizing other controls or elements in a window (or any other container).

?
Figure 1. Manipulating Child Items: The yellow outline around the layout grid in the object tree indicates that it is selected for manipulation of child elements or adding columns.

By default, a Grid has one row and one column, meaning the entire window is a single cell, which behaves very much like a Windows Forms window. You can drop controls into the cell, and then place and size them. Grids truly begin to add value when you add more cells. In the example application, the left and right sides of the window are independent areas. Creating a second column in the Grid provides a way to treat both sides of the window almost as if they were independent windows. You can (for instance) put controls into the “team” side of the window and arrange them within their cell. If that cell changes size for whatever reason (perhaps because the user resizes the area, or maybe because the window changed in size, or perhaps because you decide later to add another cell), you have to worry only about keeping the controls aligned and sized properly within that cell. This simplifies the overall setup of the interface. For this reason, Grid elements should be your default choice for layout in WPF.

Expression Blend makes it easy to add grid columns and rows visually. Simply select the grid in the object tree by double-clicking in it (the grid is a child of the window and appears as such in the object tree), which highlights it in yellow. It is important that the grid isn’t just selected, but it is selected for child element editing, which is what the yellow outline indicates (see Figure 1). If you’ve only selected an element (single click), you can manipulate the object’s properties, but to add child elements such as columns, rows, or even other controls such as buttons, you need to select the grid with a double click.

After selecting the grid in this way, the visual design view shows “bars” above the top end left hand edge of the grid. You can move the mouse over that bar to get an orange “ghost” indicator for a new grid row or column (see Figure 2). Click where you would like the new column to appear.

?
Figure 2. Adding Rows and Columns: You add a new grid cell using the mouse and the visual designer.
?
Figure 3. Changing Column Properties: You can change column definition properties through the Properties pane.

For this example choose to add the new column at a location about one-fourth the width of the window. After adding a column, you can change the width by dragging the column at the very top. You can also change column widths (or row height) through the Properties pane (see Figure 3). To do that, make sure you’ve selected the grid in the object hierarchy and click on the ellipsis (?) button next to the ColumnDefinitions property in the Layout category in the Properties pane.

Author’s Note: You may need to extend the Layout category to see the property.

Note that by default, the width of the column will be set to something like “0.266 Star.” WPF lets you define the width of columns in either pixels or stars (*). Pixel widths are absolute width definitions based on logical pixels (one logical pixel is 1/96th of an inch, which maps to one pixel on a standard monitor, but may map to something else on high-res monitors). The star definition is similar to percentages. For example, you could set the width of column one to 25* and column two to 75* to achieve a 1:3 ratio. However, unlike percentages, star definitions do not have to add up to 100 percent?you could achieve the same spread by setting the first column width to 1* and the second column to 3*. This often simplifies the overall setup.

If you were to add an additional column on the right whose width is equal to the left column, you could simply add one more column with a 1* width definition, rather than having to reset the percentages of all columns. This feature is especially useful in complex scenarios.

To make the two sides resizable, you’ll use a GridSplitter. These objects automatically dock to the sides of a cell and provide a resize/slider grip for users. When a user moves the slider, the grid cells automatically resize. You could simply drop a GridSplitter into the second cell of the grid and dock it to the left edge of that cell. Unfortunately, the splitter has a certain width (typically about 3 pixels) that you have to subtract from the available area in the second cell, making the cell layout significantly more complex, especially if you want to change the splitter’s width or remove it entirely. A more manageable approach is to add an additional and very narrow cell between the two existing cells and use that exclusively for the splitter.

To do so, add a grid cell before the second one and set its width to three pixels. Then, choose a GridSplitter from the Toolbox and place it inside the second cell. Set the splitter margins to zero on all four sides. Be sure you set it so it will stretch both horizontally and vertically. Also, you should set the Height and Width properties to Auto (you can reset that value to Auto by clicking the tiny white square to the left of the property value, which brings up a menu). This ensures that the splitter uses up the entire column area. Creating a special column just for the splitter greatly simplifies grid splitter management, so you should always place GridSplitters in their own columns or rows.

Note that you don’t need to change the width definition of the two previously existing columns. The definition for this example simply means that you have a column three pixels wide, regardless of the overall width of the grid. The other two columns will use up the remaining width at a 1:3 ratio. This demonstrates how much easier the star system is than a percentage-based system. What is the percentage of a 3-pixel wide column? There is no right answer to this question because that depends on the overall width of the grid (and the window that hosts the grid). This was one of the classical problems of percentage-based definitions (as used by HTML for instance) that has been solved elegantly with the star system.

You can also inspect the XAML for the UI so far by clicking on the XAML tab. The following snippet shows the grid portion only:

                        

Adding Controls, Data, and Behavior

Now that you have the basic layout in place, you can begin adding controls. This example uses ListBoxes to show the list of teams and player roster for a team. In standard Windows Forms applications, developers use ListBox controls to display simple lists, most of which are short and ugly. In WPF/Silverlight on the other hand, developers use ListBoxes as workhorse objects to display large amounts of data in very flexible ways.

Add Listbox controls to both the first and third columns. Make sure you set their width and height to Auto and their vertical and horizontal alignments to stretch. Also, set the margins of the outside edges to 8 pixels, and the margins for their inside edges (near the GridSplitter) to 2.5 pixels (because the grid splitter automatically adds some “whitespace” between the two list boxes). This creates a nice overall appearance, no matter what size the main window is, and no matter how the user chooses to size both “panels.”

?
Figure 4. Declarative Data Binding: In some cases, binding to CLR objects can be completely declarative and may not require any coding.

Now you need to bind the two lists to data. Given the right preconditions, WPF/SL can bind to data in a downright simple way. For instance, you can bind controls to an XML file or a .NET object that acts as the data source without writing any code. However, such objects must be creatable without any constructor parameters or any method calls of any kind. In other words, you couldn’t call a business object that returns a DataSet. Instead, a simple New operation must be sufficient.

In the real world, you are not very likely to use XML files as data sources for sophisticated applications (although XML served up by a web service is a more likely scenario). Most applications use objects of some sort. Most real-world scenarios require involved method calls or instantiation parameters to indicate what data you want to load. However, the example for this article happens to be a team data object that you can instantiate without any parameters. On creation, that object loads all the teams from the database and exposes them as a collection object. That’s convenient for example purposes, but it is somewhat unusual. You’ll see how to call more common data sources when you see how to populate the Players list.

To bind the Teams list to data, right-click it and select “Bind ItemsSource to Data?” from the context menu. This launches the Create Data Binding dialog box shown in Figure 4. Click the “+ CLR Object” button to get a list of all the CLR objects available in the current project that may be used as data sources.

Author’s Note: Make sure you have added a reference to your middle-tier assembly in your project.

?
Figure 5. Basic Data Template: Define a very basic data template for each item in the teams-list.

Close the dialogs and run the application (press F5 either from Blend or Visual Studio after saving all files) to see the data binding in action. At this point, the list does not look very nice, because it’s simply bound to a list of TeamBusinessEntity objects, without specifying what fields from within those objects are to be displayed. Therefore, the list displays only the default ToString() result for each row, which is simply the name of the object. To fix this problem and display the specific property (or multiple property) values, you need to define a data template.

Right-click on the Teams list and select the Create Data Binding option. This brings up a dialog box (see Figure 4). Click the “Define Data Template” button, which launches the Create Data Template dialog box shown in Figure 5. To define a data template, pick one or more data source members to display inside each list item. In WPF/SL, list boxes can contain complex items. In fact, each list item can be a Grid object (which is not the default and thus has to be picked explicitly), which?as you saw above?is its own microcosm that can include just about any other object.

Using a Grid as the container object will ultimately allow you to create an elaborate design for each list item. Initially, however, just put a text block inside the grid that is bound to the team name. Finally, check the “Generate sample data” checkbox. This will create nonsensical sample data during design time (names of fruits), that is nevertheless convenient to have, because it forces the list box to show items in the designer, enabling you to see the impact of settings and changes immediately, without having to run the application.

You can now run the application and see the data binding in action, including the correct display of team names.

What is missing at this point is the display of the players when a team is selected. As noted above, this is a little trickier than the display of teams because you have to make a call to a middle-tier object to retrieve an appropriate list of players from a potentially very large list of players stored in the database. So you can’t just pick an object in a Blend dialog. Instead, you have to write an event triggered when a user selects a new item. The event code must retrieve the appropriate data and assign that to the second list box as its data source. The following code snippet shows an event handler that accomplishes just that:

   private void lstTeams_SelectionChanged(      object sender, SelectionChangedEventArgs e)   {      if (this.lstPlayers != null)      {         var teams = this.lstTeams.ItemsSource            as HomeLeagueTeams;         Guid teamId = teams[           this.lstTeams.SelectedIndex].PK;         PlayerList players =             new PlayerList(teamId);         this.lstPlayers.ItemsSource = players;      }   }

Wire up this code to the SelectionChanged event by double-clicking that event in the event list in Blend (the event list is the secondary mode of the property grid), which automatically switches to Visual Studio (or launches it if you haven’t started it already) and creates the empty event handler code.

The code itself makes sure the player list has been initialized (because it’s possible this code could get called during initialization of the team list?before the player list has ever been created). Then, it retrieves a reference to the data source, which retrieves data using the primary key (PK) of the currently-selected team. It returns a PlayerList business entity, which is a middle-tier object that represents a list of players.

Author’s Note: Your implementation of the middle tier may vary drastically, but the overall idea of writing some code that ultimately returns appropriate data remains the same.

The returned data is then assigned as the data source for the Players list. (Note that I used Blend’s property grid to assign names to both list boxes.)

If you run the application now, you will see that everything works, sort of?but the Players list has the same flaw that originally happened with the first list; instead of player names, it displays only the object name for each bound object. The root problem is the same as before: You need a data template that defines which data elements to show in each list item. You’ll have to fix this problem using a different technique than before, however, because you cannot use Blend’s data binding dialog box. One approach is to create a new data template from scratch by right-clicking on the second list box and picking the menu option Edit Other Templates ? Edit Generated Items (ItemTemplate) ? Create Empty. However, there’s a simpler trick. Because you already have a similar template in the first list box, you can simply apply that template, save it as a new template, and then modify it to bind the text block to the appropriate property. To do this, right-click the list box and select Edit Other Templates ? Edit Generated Items (ItemTemplate) ? Apply Resource, and then pick the existing template you created earlier.

?
Figure 6. Editing Bound Properties: Bound properties appear outlined in yellow in the property sheet.

At this point, both lists use the same data template, which is now shared between them. That’s not exactly what you need, because you want the second list to bind to a differently named property. While each team name is simply stored in a Name property on the data object, player names are stored in a SearchName property. So you need to change the binding expression?but not in the shared template: that would break the first list. Instead, save a copy of the assigned template, giving the second list its own version of the data template, which you can then modify without breaking the first one. To do that, right-click the control again and from the menus choose Edit Other Templates ? Edit Generated Items (ItemTemplate) ? Edit a Copy?. Choose a name for the new template. Blend then automatically switches into visual template-editing mode. If you’re following along, you can click on the text block and observe how the Text property has a yellow outline in the property sheet (see Figure 6). Click the little yellow square to the right of the property value to bring up the context menu and pick “Data Binding?”. In the dialog box, change the “custom binding expression” to SearchName, and click Close. Run the application again to see it in its fully functional form.

Adding Design and Polish

At this point, the application is functionally complete, but you certainly couldn’t call it beautiful, well designed, or polished. But it’s easy to enhance by adding some simple design elements. This example uses a dark color scheme similar to the design chosen by Blend itself, and also by Vista, Office 2007, and other applications. Feel free to substitute a color scheme that is more to your liking.

?
Figure 7. Subtle Gradient: The sample application uses a subtle linear gradient applied to the window background, from black to a color that is just slightly off-black.

First, change the window background to black (or another color of your choice). However, con’t set it to a solid black because that usually looks artificial and “computer graphic-y.” Instead, set the background to a simple linear gradient that starts out pure black in the top-left corner and is just slightly off-black in the bottom-right corner. Creating subtle gradients is a simple trick that often results in a more polished look. In nature, nothing is just a single color. When you look at a wall, for instance, due to lighting in the room, its color will vary slightly over different parts of the wall, even though the wall itself is painted in just a single color. A wall with exactly the same color everywhere would look unnatural to the human eye. Therefore, creating a subtle gradient looks very natural and “right.” This trick works only on a subconscious level. If users actually notice the gradient, the trick falls apart. Therefore, keep the two gradient colors close, and use colors from the same color family. A gradient from a dark red to a dark green is never subtle. Figure 7 shows the property settings for a black to slightly off-black gradient.

Another simple trick with gradients is to avoid making them run exactly vertical or exactly horizontal (unless you want to simulate a material that has just such a property, as in the glass example below). You can use the “Brush Transform” tool from the Blend Toolbox to easily change the angle of the gradient. Select the root layout grid (you’ll apply this effect to the grid, not the window, although in this example you could have chosen one or the other with equal success) and pick the Brush Transform tool, which shows a big arrow in the design window. Simply drag the start of the arrow to the top-left corner of the grid/window, and the end of it to the bottom-right corner.

You can now launch the application to see the resulting effect. However, you will quickly notice that not much of the effect is visible, because the list boxes use up almost the entire window. To see more of the effect, set the background brushes of both lists to be only 10 percent opaque. This will make the individual items hard to read for now, but I’ll show you how to address that later. Now, run the application to see the initial design. It still isn’t very fancy, but it’s definitely a start towards creating a unique experience.

Next, you can redesign each list item so it has a more advanced look. You’ll also see how to take the first step towards achieving separation of UI implementation from UI design, by putting the design into a separate file, also known as a resource dictionary. This change lets developers work with the actual window while designers work with the dictionary without stepping on each other’s toes. As an added benefit of this design, you can switch the applied design on-the-fly, creating new skins.

To initiate the process, right-click on the first list, and from the context menu, pick Edit Other Templates ? Edit Generated Items (ItemTemplate) ? Edit a Copy?. Enter a descriptive name for the template (such as TeamListItemTemplate) and choose the option to define the template inside a resource dictionary. Because you haven’t created a dictionary yet, click the New? button, specify a filename for the dictionary (such as BlackSkin.xaml) and then choose to store the template in that dictionary.

Blend automatically puts you in template editing mode as a result of the preceding steps. Select the grid (the root layout element of the template) and set its width to 150 pixels, and the height to 185 pixels. This explicitly defines the height of each item in the team list, and provides some extra space for each list item?and a look that’s distinctly different from conventional Windows list box items. Because each list item is itself a grid, you have great freedom in designing each item. Continuing with the “black skin” approach used so far, I chose to implement a black “glassy” look for each item. Glass effects are currently all the rage, and can be produced easily without much artistic talent, as you’ll see.

Author’s Note: Author’s Note: I chose this example theme because it is currently in fashion. Many applications?including Windows Vista and Microsoft Office 2007?use this style, and it’s relatively easy to create. In future installments of this article series, you’ll see other themes and techniques as well.

Add a rectangle shape to the grid. Set its margins to four pixels on each side. Change the RadiusX and RadiusY properties to 10 pixels each to create a rounded rectangle. (Note that you can also do this through the visual design surface by dragging the corner radius adorners). Then pick the stroke brush and set it to No brush, because you don’t need an outline for the rectangle. You do, however, want a background brush, so create a brush that flows from solid black at the top to slightly off-black at the bottom. (The gradient direction is exactly vertical in this case.)

Add a second rectangle to the very top of the item’s grid. Make the height 25 pixels and the right, top, and left margin 5 pixels. Make the corner radius 10 pixels on each dimension as well. Again, you don’t need an outline brush, so set it to No brush. Now, for the first glass effect, create a vertical background brush with a gradient from solid-white to solid-white. However, set the Alpha channel value of the top color to 15 percent, making it almost entirely transparent. Then set the Alpha value of the bottom color to 0%, making it completely transparent. Next, add another gradient by clicking a pixel or two to the left of the center of the gradient line in the property grid. Make it white as well, with an alpha setting of 25 percent (a little less transparent, thus making the white more visible). Add another gradient stop a pixel to the right, set it to white, and set its alpha value to 10%. This creates quite a sharp edge between the two gradient stops, which have to be close together. (One characteristic of glass is that it has sharp edges and reflections.)

Right-click the text block in the object tree and choose “Order ? Bring to Front” to show the text label as the topmost object. Then, in the property grid, change its vertical alignment to Top, change the Height to 21 pixels, set the font to 14-point bold. The foreground color has to be solid white, and the text alignment (in the paragraph tab of the Text category in the property sheet) should be set to Center. You also need a margin around the object, so set the right and left margin to four pixels and the top margin to eight pixels.

Figure 8 shows the template in design mode. To see the result (displayed in Figure 9), run the application.

?
Figure 8. Team Item Data Template: The figure shows the data template for a team item in design mode. Note the gradient settings for the background brush.
?
Figure 9. Running Application: Here’s a preliminary version of the application at runtime using the data template.

Adding Images and Shiny Logos

The final piece in this template involves adding team logos. The middle tier provides the team logo as a property on each team object. However, this property is a GDI+ bitmap object, which WPF does not natively understand. Also, you’ll have to make some adjustments, because you can’t be sure about the image’s size, and you’ll need to ensure it fits into the list item perfectly.

I’ll show you how to address the size problem first. Drop a Viewbox element from the Blend Toolbox (you may have to go into the “Asset Library” button of the toolbox, which is the bottom-most button and provides access to an extended set of UI elements) and position it inside the grid with a margin of 12 pixels around the left, bottom, and right edges. Set the top margin to 35 pixels so the Viewbox doesn’t interfere with the label at the top. Viewboxes are very handy elements because they automatically resize everything inside them to take up the exact amount of room provided by the Viewbox itself. Using a Viewbox means you can now drop an image object inside the viewbox and it will resize as needed to use up exactly the desired space.

To do that, double-click the Viewbox in the object tree. It will now appear with a yellow outline, indicating that future objects dropped on the design surface will be added as children of the Viewbox. Now drop an Image object inside the Viewbox, set its height and width to Auto (reset if necessary), and then set the margin around the image to 0 on all sides. Then, find the Source property in the Property pane, and click the small rectangle to the left of the property value to bring up the context menu. Select Data Binding? from the menu. In the dialog box, pick the Explicit Data Context page and set the Custom Expression to TeamLogo. This binds the WPF Image element to the GDI+ image provided by the bound object.

You still need to convert that image to something WPF understands: an ImageSource object. For this you’ll use a value converter. Listing 1 provides such a converter for bitmap objects.

The converter needs to convert only one way: bitmaps to image sources. To use the value converter, expand the data binding dialog and pick the value converter you just created. Also make sure you set the binding direction to Default.

Because you’re defining the data template in an external resource dictionary, the dictionary may not be aware of the value converter object. You may have to open the XAML file manually and add your namespace to the XAML definition and a resource reference to the value converter as well. Theoretically, Blend should do this for you, but I have had mixed results getting this to work.

The following code snippet illustrates what the first few lines in the XAML file should look like:

                     ...

Also, I’ve sometimes had trouble setting all the aforementioned binding properties through the data binding dialog box. If that fails, you can also touch it up manually in the XAML file. This code snippet shows what the binding should look like:

   

This should do the trick. The logos should now show up correctly and at the right size. As a final tweak, I’ll show you how to add a glass effect over the logo as well.

Drop another rectangle onto the grid (double-click the grid to make sure you add the child elements to the grid rather than the Viewbox.) The rectangle should have no rounded corners. Set the rectangle’s left and right margin to four pixels to use up almost the entire available width. Set the top margin to 30 pixels and the bottom margin to 80 pixels. Set the background to be a vertical gradient from white to white, with a top alpha value of 0% (fully transparent) and a bottom alpha value of 15% (not quite fully transparent, providing a slight white hint).

?
Figure 10. Logos with Glass Effect: The new data template includes a logo converted from a GDI+ bitmap. Note the curved glass effect across the logo.

Here comes the trick: With the rectangle selected, right-click to open the “Object” menu, and choose Path ? Convert to Path. This changes the rectangle to a fully editable polygon that just happens to be a rectangle at this point. To edit individual segments of the path, activate the Direct Selection tool in the toolbox (second arrow icon from the top). That tool lets you not only select a complete object, but also edit elements within an object. Then, hold down the ALT key, move the mouse over about the middle of the bottom line of the rectangle, click on it, and drag it down about 10 or 15 pixels. Doing that turns the bottom line into a curve, and gives you a curved glass effect overlapping the logo (see Figure 10). (You can see a similar effect in the icon at the top-right edge of the Vista Aero start menu, by the way.)

Where’s the Middle Tier and the Data?

To build the sample application, I picked an existing middle tier and database to provide a real-world view of what one can expect when building WPF or Silverlight UIs on top of existing code. That’s why the middle tier in this example serves up GDI+ bitmaps, rather than anything WPF understands natively, providing an opportunity to teach an interesting technique in the process. However, because the application example is a real-world app, I was not able to ship it as a downloadable example. For this reason, I created a downloadable sample version of the middle tier that I can provide if you email me. (Thanks to Jon Herrell for his help in this.)

That’s it for this installment. The next article in this series will show you how to add additional graphical effects and various professional-looking animations. I’ll even re-define how list boxes create layout for all their contained items and turn them into lists with an appearance unlike any other you have ever seen in Windows. Furthermore, I’ll show you how to re-style some standard elements that do not quite fit in with the design yet. Eventually, I’ll demonstrate how you can re-style the application with a completely different look. So stay tuned.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist