PF’s new control set includes both familiar controls, such as the Label and TextBox that do more or less the same thing as their Windows Forms counterparts as well as new and unfamiliar controls, such as WrapPanel and Expander, which provide useful new features.
This article provides a brief overview of the most useful WPF controls, in alphabetical order. It explains broadly the purpose of each and, for the more complicated controls, gives a few hints about using them.
Before delving into the controls themselves, it’s worth discussing two WPF features that give WPF controls abilities that Windows Forms controls lack: support for DirectX, and a more general content model.
As discussed in the first article in this series, one of WPF’s goals is to take advantage of modern graphics hardware. WPF achieves this by using DirectX to build its controls, giving them such benefits as faster rendering, better video support, and transformations. Transformations give you the power to move, rotate, and stretch controls easily.
For example, the UsesDirectX sample program shown in Figure 1 (available in the downloadable code in both C# and Visual Basic versions) displays a group of controls that have been rotated by 20 degrees. The colorful control in the middle is a MediaElement control displaying a video of a Julia Set fractal.
|Figure 1. Terrific Transformations: Because they are built with DirectX, WPF controls support transformations such as translation, scaling, and rotation.|
The second basic change (which is less cool but probably more important than rotated video controls) is that WPF controls support a more complex content model than Windows Forms controls. In Windows Forms, many controls can hold a single specific piece of information. For example, the Windows Forms Label and Button controls have a Text property that determines the text the controls display. A Button control can also display an image?but that’s about it. You can’t, for instance, place a TreeView control on a Button or put a video file in a Label.
But, regardless of the wisdom of doing so, such operations are quite possible in WPF. That’s because instead of a single Text or similar property that determines control contents, most WPF controls have a Content property that lets them hold just about anything. A Button can contain simple text, a Label, a TextBox, a MediaElement playing a video, or even a TreeView. WPF automatically handles the events generated by whatever is inside the Button, so clicking on the contents makes the Button raise its Click event just as you would expect.
|Figure 2. Captivating Controls: Program ControlSamples demonstrates most of the key WPF controls.|
Many WPF controls can hold multiple child controls but even those that can hold only a single child are not particularly restricted, because that single child can be a container control that holds multiple children.
For example, the rotated group of controls shown in Figure 1 is actually one large Button containing a Grid that holds a set of Label, Image, and MediaElement controls. If you click on any of them, the Button raises its Click event (which restarts the video in the demo).
As you read through the following sections describing specific control types, you’ll learn which ones are designed to hold a single child (Label, Button) and which can contain and arrange many children (Grid, StackPanel). After you get the hang of WPF’s new content model, you can compose controls to build all sorts of interesting and powerful user interfaces.
With that background out of the way, the following sections describe the most useful WPF controls. The ControlSamples program (also in the downloadable code) shown in Figure 2 demonstrates the controls discussed here.
|Author’s Note: The ControlSamples application is intended purely for demonstration purposes; I don’t generally recommend putting every possible control on a single window.|
The Border control draws a border around its single child control. If you want to put more than one control inside the Border, make the child a container such as a Grid and put the other controls inside that.
The control’s CornerRadius property determines the radius of curvature for the Border’s corners. Set CornerRadius to 0 to get square corners.
The BulletDecorator displays an item in a bulleted list. The control’s Bullet property is an object that represents the bullet to display. Next to the bullet, the control displays a single child, normally a Label or TextBlock.
The following XAML code shows how program ControlSamples draws the first item in the bulleted list shown in Figure 2.
The Button control behaves much like its Windows Forms counterpart. When the user clicks it, the Button raises its Click event.
The only interesting thing to note here is that the Button can only contain a single child, but you can make that child a container such as a Grid or StackPanel so it’s not much of a restriction. The big Button shown in Figure 1 contains a Grid that holds a bunch of other controls.
A Canvas is a container control that lets you explicitly position its child controls by setting their properties. The Canvas provides attached Top, Left, Bottom, and Right properties that determine a child’s position. You set the control’s Height and Width, together with either Canvas.Left or Canvas.Right and Canvas.Top or Canvas.Bottom.
For example, the following code shows how program ControlSamples creates the yellow Canvas control and its two Rectangles on the left in Figure 2.
The first Rectangle’s Canvas.Top and Canvas.Left properties position the control 10 pixels down and to the right of the Canvas’s upper left corner. The second Rectangle’s Canvas.Right and Canvas.Bottom properties position it five pixels left and up from the Canvas’s lower right corner.
The CheckBox behaves much as the Windows Forms version does, with as few properties renamed. Instead of Checked, this version uses IsChecked to determine whether the box is checked. Similarly, it uses IsThreeState rather than ThreeState to determine whether the control allows three states: checked, unchecked, and indeterminate.
Instead of a CheckChanged event, the control fires separate Checked and Unchecked events when users check or uncheck it.
Like its Windows Forms counterpart, the ComboBox displays a dropdown list of items that the user can select. The control provides SelectedIndex, SelectedItem, and SelectedValue properties to let you get or set the current selection.
The ComboBox contains a set of ComboBoxItem controls that hold the choices. Each ComboBoxItem can display a simple text value or hold a child control?possibly a container that holds other controls.
The following code shows how the ControlSamples program defines its ComboBox. (It’s on the left below the CheckBoxes displaying the confused face and the text “Confusion.”) The first and last items display simple text while the middle item displays a StackPanel containing an Image and a Label. The second item is selected in Figure 2 so you can see the result.
The ContextMenu displays a popup menu for another control. The control should have a ContextMenu attached element attribute that contains a ContextMenu element, which in turn should contain MenuItems that provide the commands users see in the menu.
The following code builds a Label that contains a ContextMenu.
The DockPanel is a container control that can attach its children to its edges. The child controls can use the attached DockPanel.Dock property to indicate the edge to which they should dock.
The sequence in which you add children to the DockPanel determines their attachment order. Each time it reaches a new child, the DockPanel attaches it to whatever portion of the control is left unclaimed by previous children.
The following code shows how ControlSamples defines its DockPanel and the Labels it contains. For simplicity, the following code by omits the Labels’ BorderBrush and BorderThickness properties that give them the outlines shown in Figure 2:
When the DockPanel’s LastChildFill property is true (which it is by default), the control fills any remaining space with its last child.
|Figure 3. Determined Document: The DocumentViewer displays fixed documents much as Adobe Acrobat displays PDF files.|
The DocumentViewer displays fixed content, much like Adobe Acrobat displays PDF files. The UseDocumentViewer program shown in Figure 3 contains a DocumentViewer displaying a fixed document. If you resize the window, the DocumentViewer resizes, too, but the document remains unchanged. The text still appears at exactly the positions shown in Figure 3.
Unfortunately, the structure of a fixed document is too complex to cover in detail, but briefly, it contains a FixedDocument, which contains one or more PageContent objects. Each of those contains a FixedPage object that contains the document’s interesting content: StackPanels, Labels, TextBlocks, and so forth.
Download the UseDocumentViewer program and look at its XAML code to see how this works.
Note that neither Expression Blend nor Visual Studio understand fixed documents very well, so their designers display error messages instead of content when you work with these controls, although the program still runs. If you need to work with FixedDocuments, use the sample program as a starting point and try to ignore the errors as you build your own programs.
The Ellipse control draws a simple ellipse. The control’s Fill and Stroke properties determine its interior and edge colors. Other stroke properties, such as StrokeDashArray and StrokeDashCap, control the edge’s appearance.
The following code shows how ControlSamples draws its ellipse (see Figure 2).
The Expander control displays an arrow button that users can click to expand or hide the control’s single child. Its IsExpanded property determines whether the control is currently expanded. The Header property determines what (if anything) the control displays next to its button.
Here’s how ControlSamples creates its Expander. In this example, the Expander contains a Border that holds a StackPanel containing several Labels.
Unlike the fixed document displayed by the DocumentViewer, a flow document’s contents can flow as the available space changes, in much the same way that a web browser reflows a page of HTML when the browser resizes.
Like the fixed document, the flow document’s structure is too complex to cover here, but basically, a FlowDocument contains Paragraph, Table, BlockUIContainer, and other objects that hold the document’s content.
WPF includes three controls for viewing flow documents in different ways:
|Figure 4. Preferred Pageviews: The FlowDocumentReader displays flow documents in page, scroll, or two-page mode.|
- The FlowDocumentPageViewer displays the document in page mode as a series of single pages that fit the viewer’s current size.
- The FlowDocumentScrollViewer displays the document as a single scrollable page like a web page.
- The FlowDocumentReader can display the document in page mode, scroll mode, or a side-by-side two-page mode.
Figure 4 shows a FlowDocumentReader displaying a document in two-page mode. The buttons on the bottom right of center let you change the control’s viewing mode.
Download the UseFlowDocumentReader example program and experiment with it to get a better idea of the control’s display modes.
Most Windows developers think of Frame controls as a sort of group box with a header and a border. However, the WPF Frame control is a navigation control. It displays content and provides browser-like navigation tools that let you move forward and backward through an internally-maintained navigation history.
You can set the control’s Source property to a URL that you want it to display. At run time, your program can use the control’s Navigate method to go to a new URL. For example, the following C# code makes the Frame control named frmVbHelper open the web page http://www.vb-helper.com.
|Figure 5. Nifty Navigation: The Frame control displays content such as web pages and provides browser-like navigation.|
The control also provides methods that let you control the navigation from code. For example, the GoBack and GoForward methods move forward and backward through the navigation history.
|Author’s Note: If a user navigates to a new page by clicking a link on a web page, the Frame does not add the new page to its navigation history.|
Figure 5 shows the UseFrame program example displaying a web page. The buttons along the top call the Frame’s Navigate method to display new web pages. Below those buttons, you can see the navigation arrow buttons provided by the Frame control.
The Grid control is one of the more powerful container controls provided by WPF. It divides its area into rows and columns that can contain child controls.
You define the Grid’s row and column sizes by setting its Grid.RowDefinitions and Grid.ColumnDefinitions property elements. The Grid.RowDefinitions element should contain RowDefinition objects that define the rows’ heights, while the Grid.ColumnDefinitions element should contain ColumnDefinition objects that define the columns’ widths.
The real layout power of the Grid occurs because you don’t need absolute values. You can set a height or width to a numeric pixel value or you can use a “star” syntax that includes a number followed by an asterisk. After subtracting any space reserved by explicit pixel values, the control divides its remaining space among the “star” rows/columns by calculating a weighted average of their numeric values.
For example, if one row has height 1* and another has height 2*, then the first row gets 1/(1+2) = 1/3 of the available height and the second row gets 2/(1+2) = 2/3 of the available height.
After you define row and column sizes, a Grid’s child can use Grid.Row and Grid.Column attached properties to indicate which row and column should hold it. You can use the Grid.RowSpan and Grid.ColumnSpan properties to let a child cover more than one row or column.
The following code fragment shows how the UsesDirectX example shown in Figure 1 defines the Grid inside the program’s Button. The star syntax makes the rows and columns have equal heights and widths. To keep the code short, I’ve omitted some of the Grid’s children. Download the example to see the complete code.
... other items omitted ...
A GridSplitter lets users resize a Grid’s rows and columns at run time. For example to let a user resize two adjacent columns, place a GridSplitter in the left column. Use the Grid.RowSpan property if necessary so the GridSplitter spans all the Grid’s rows vertically. Set the control’s Width so it’s big enough for the user to grab. Now at run time the user can click and drag the control to resize the Grid’s columns.
|Author’s Note: Tip: Be sure to define the GridSplitter in the code after any other controls in the same column so it sits on top of them instead of being hidden behind them.|
The following code shows how the GridSplitter in the ControlSamples program lets users resize the Grid’s two columns. In Figure 2, the GridSplitter is the grayish stripe between the blue “Left” label and the yellow “Right” label.
The GroupBox works much like the Windows Forms version. It draws some header text (defined by its Header property) and a border around its single child.
As in Windows Forms, the GroupBox also defines a RadioButton group, so clicking one RadioButton in the GroupBox deselects the other RadioButtons in the GroupBox. (Note that in WPF all container controls define RadioButton groups, not just the GroupBox.)
The following code shows how the program ControlSamples defines its GroupBox.
The Image control displays a picture. This control’s most important properties are Source and Stretch. Source specifies the path to the image that the control should display. This can be a path to an image inside the program or it can be a URL. The Stretch property determines how the control stretches the picture to fill the control. This property can take the following values:
- Fill: The picture is stretched to fill the control even if that distorts the picture.
- None: The picture is not stretched but is shown at full size and may be clipped if it won’t fit.
- Uniform: The picture is made as large as possible while still fitting within the control without distorting it.
- UniformToFill: The picture is made as large as necessary to fill the entire control without distorting it. Unless the picture and the control have the same width-to-height ratio, part of the picture will be clipped.
Here’s the Image control definition from the ControlSamples program:
A Label simply displays text that users can see but cannot modify or select. Normally you set the Label’s text using the control’s Content property as in the following code:
However, you can place other objects inside a Label to give it more complex content.
A Line control draws a simple line segment. Its X1, Y1, X2, and Y2 properties specify the coordinates of the line’s end points. Its stroke properties (Stroke, StrokeThickness, and so forth) determine the line’s appearance.
Like its Windows Forms counterpart, the ListBox displays a list of choices that the user can select. The WPF version, however, can easily hold text, images, and more complex items that are hard to handle with the Windows Forms ListBox.
The ListBox should contain ListBoxItem objects that define the items users can select. If an item contains only simple text, you can set it with the ListBoxItem’s Content property.
The SelectionMode property determines how the user can select items. This property can take the values Single (users can select only one item), Multiple (users can select multiple items; clicking an item toggles whether it is selected), or Extended (users can select multiple items using Click, Shift-Click, and Ctrl-Click).
When the SelectionMode is set to Single, you can use the control’s SelectedIndex, SelectedItem, and SelectedValue properties to set or retrieve the currently selected item. For the other selection modes, set the ListBoxItem objects’ IsSelected property to True or False to indicate which items are selected.
Here’s the ListBox definition for the ControlSamples program:
The ListView displays a set of child objects in several different ways. This is one of the more complicated WPF controls and a complete discussion of it won’t fit here, but I’ll cover the details in a future article.
Basically, though, the ListView contains View objects that define different views of the data. Typically a View contains a GridView that defines display columns much like those used by the Windows Forms ListView.
You use data binding to tell the GridView how to pull data out of the objects that you want to display. For a set of Book objects, for example, you might have the view display an object’s Title, Author, and Year properties in three columns. You would create a collection of Book objects and attach it to the ListView.
You can define multiple Views to show the data in different ways.
The MediaElement control plays a video or audio file. Set the control’s Source property to determine the file the control will play. The UsesDirectX program displays its video file as follows:
The control provides several useful properties and methods that let your code control it. These include the intuitively named Pause, Play, Position, SpeedRatio, Stop, and Volume.
Menu and MenuItem
The Menu control builds a menu. It contains MenuItem controls that provide the menu’s commands.
The MenuItem’s Header property, which normally contains plain text, determines what the user sees in the menu. When users select a MenuItem, it fires its Click event.
A MenuItem can contain other MenuItems to make submenus.
Unfortunately, a MenuItem does not automatically appear at the top of a Window and it does not automatically reserve space for itself. If you simply put a Menu on a Window with other controls, it might end up in a strange position overlapping those controls.
Probably the easiest way to handle this is to give the Window a DockPanel and set the Menu’s DockPanel.Dock property to Top.
The PasswordBox is a simple text box that hides the characters that it contains. The PasswordChar property determines what character is displayed instead of the characters that users type (by default it displays a dot). The Password property contains the password the users entered in the control.
The Path control draws a series of lines and curves. It can draw everything from a single line segment (in fact, Expression Blend’s Line tool actually draws a Path that contains a line) to a complex Bezier curve.
The easiest way to use the Path control in XAML is to set its Data property to a series of commands written in the Path mini-language. Table 1 describes the language’s commands very briefly. Note that many commands have both uppercase and lowercase versions; the uppercase version means the following points are in absolute coordinates, while the lowercase version means the points are relative to the previous points.
|F0||Use odd/even fill rule so areas within a self-intersecting curve may not be filled.|
|F1||Use non-zero fill rule.|
|M or m||Move.|
|L or l||Draw lines.|
|H or h||Draw a horizontal line.|
|V or v||Draw a vertical line.|
|C or c||Draw a cubic B?zier curve.|
|S or s||Draw a smooth B?zier curve.|
|Q or q||Draw a quadratic B?zier curve.|
|T or t||Draw a smooth B?zier curve defined by a single point, using previous T commands to generate control points. The result is a smooth curve that passes through the points sent to consecutive T commands.|
|A or a||Draws an elliptical arc.|
|Z or z||Close the figure by connecting the current point to the first point.|
The ControlSamples program uses the following code to draw its Path:
In Figure 2, small Rectangle objects show where the Path’s control points are.
|Author’s Note: See the online help for more information on the Path mini-language.|
The Polygon draws line segments connecting a series of points. It finishes by connecting the last point to the first.
To use the Polygon, set its Points property to the coordinates of the points that it should connect. The following code shows how program ControlSamples draws the yellow and red diamond.
The Polyline is similar to the Polygon except it doesn’t automatically connect the first point to the last point. The following code shows how program ControlSamples draws the blue and red unclosed diamond.
Even if the first and last points have the same coordinates, the Polyline control doesn’t produce exactly the same result as the Polygon. The Polygon treats that spot as a corner in the polygon, but the Polyline treats it as just the place where the first line starts and the last line ends. If the shapes’ StrokeThickness values are very thick, you can see the difference.
|Author’s Note: Polyline and Polygon controls provide the same stroke and fill properties for determining color and line style that other drawing controls provide.|
The Popup displays a floating area over the Window. Context menus, tool tips, and other floating features use the Popup to do their jobs and you can usually use those instead of using Popup directly. However, you can use a Popup to display a floating area programmatically at times when a ContextMenu or ToolTip isn’t appropriate.
|Author’s Note: The Popup sits above all applications?not just yours?and it doesn’t move when a user moves your application. That can produce some unexpected and confusing results, so use this control carefully.|
The following list summarizes key Popup properties that control its behavior and appearance.
- IsOpen: Determines whether the Popup is visible.
- PlacementTarget: The object relative to which the Popup is positioned.
- Placement: Determines where the Popup is relative to the PlacementTarget. This can take values such as Top, Bottom, Left, Right, and Mouse. For more information, see the online help.
- HorizontalOffset: A horizontal offset for the Popup’s placement.
- VerticalOffset: A vertical offset for the Popup’s placement.
The following code shows how the ControlSamples program displays a Popup below the yellow and red diamond.
The ProgressBar displays progress information in much the same way as its Windows Forms counterpart.
The control’s most important properties are Minimum (the smallest amount the bar displays), Maximum (the largest amount it displays), and Value (the current value).
The RadioButton displays an exclusive choice. If the user selects one RadioButton in a group, all others in the group automatically deselect.
Note that, in WPF, any container defines a RadioButton group. If you put two sets of RadioButtons in different containers (DockPanels, Canvases, or whatever), then selecting a RadioButton in one group won’t affect the RadioButtons in the other group.
The Rectangle control draws a simple rectangle. Use the Margin property to determine the control’s position, and the Width and Height properties to determine its size.
Rectangle provides the same stroke and fill properties for determining color and line style as other drawing controls.
Like the Windows Forms version, the RepeatButton acts as a button but fires repeated Click events if the user holds it down.
The control’s most important properties are Delay (the number of milliseconds between the mouse press and the first repeat Click) and Interval (the number of milliseconds between subsequently fired Click events). By default, Delay is 500 and Interval is 33. When a user presses the button, it raises a Click event. Half a second later, it generates the second Click event. It then fires another Click event every 33 milliseconds after that until the user releases the button (the timing may not be exact).
The RichTextBox is similar to the Windows Forms version to the extent that they can both display Rich Text Format (RTF) content; however that’s about as far as the similarity extends. The WPF version uses different properties and methods to format its contents.
The RichTextBox provides a plethora of advanced features, including formatting (bold, italic, bulleted list, numbered list, fonts, colors), undo and redo, and automatic spell checking with a suggestions popup. It even provides a set of editing commands with keyboard shortcuts that let users apply many formatting commands without you having to include any extra code in your program. You can find a list of the editing commands on MSDN.
You can also use the editing commands from code. For example, the following C# code toggles whether the currently selected text is part of a numbered list in the RichTextBox named rchBody.
The RichTextBox is quite complicated so there isn’t room to cover it in depth here. For more information, see the online help.
Normally you don’t need to use ScrollBars directly because other controls such as ListBox, ScrollViewer, and TextBox provide them automatically, but you can use a ScrollBar to let the user select a value if you want. The WPF ScrollBar works much like the Windows Forms version does, providing relatively intuitive Minimum, Maximum, and Value properties, and a ValueChanged event.
The ScrollViewer displays one child inside a scrolling window. The control is pleasantly easy to use?simply drop a child into it such as an Image with its Stretch property set to None.
Two important ScrollViewer properties are HorizontalScrollBarVisibility and VerticalScrollBarVisibility, which determine when the control’s scroll bars are visible. Their values can be Auto, Disabled, Hidden, or Visible. (For some strange reason, HorizontalScrollBarVisibility defaults to Disabled and VerticalScrollBarVisibility defaults to Visible. You’ll probably want to set both of these to Auto.)
The Separator places a separator in a menu or toolbar.
The Slider control is somewhat similar to the Windows Forms TrackBar control. Both allow the user to select a value from a sliding scale and provide Minimum, Maximum, and Value properties. The following list describes the other most useful Slider properties.
- IsSnapToTickEnabled: Determines whether the control’s value snaps to the nearest tick mark.
- IsSelectionRangeEnabled: Determines whether the user can select a range of values.
- TickFrequency: The spacing between tick marks.
- TickPlacement: The location of the tick marks. This can be BottomRight (bottom or right depending on the orientation), TopLeft (top or left), or Both (both top and bottom, or both left and right).
- Ticks: An array of positions to place tick marks.
The StackPanel is an extremely useful container that arranges its children closely packed in either a single row or a single column. For example, the following code shows how the ControlSamples program places information inside its Expander. The StackPanel packs the three labels one after another vertically.
ControlSamples actually uses several StackPanels to make its columns of controls. It also uses StackPanels to arrange smaller groups within the columns, such as the horizontal groups holding the Polygon and Polyline, ScrollBar and Label, and Slider and Label.
StackPanel and Grid are probably the most-used WPF container controls.
The StatusBar displays an area (normally at the bottom of the form) where you can display status information. The StatusBar should contain StatusBarItems that hold the controls that you want to display.
A StatusBarItem can contain Labels, Buttons, Sliders, and even containers such as Grids that can hold other controls; however, you should generally keep the StatusBar contents simple.
The TabControl (yes, the word “Control” is part of its name) displays a set of tabs. When you click on a tab, the control displays the corresponding content.
The TabControl holds a set of TabItem objects. The TabItem’s Header property determines what is displayed in the tab. Each TabItem should contain a single child that holds whatever you want to display on the tab. Typically this child is a container such as a Grid or StackPanel that holds other controls.
The following code shows how ControlSamples makes its TabControl.
The TextBlock displays read-only text like a Label, but also supports additional features such as word wrapping, italics, bold, and colored text.
There’s no room for a full discussion of the TextBlock here but thinking of it as a fancy Label will take you pretty far. You can use Run objects inside the control’s contents to temporarily change the text’s style.
The following code shows how the ControlSamples program displays its TextBlock.
The TextBlock can display bold, italic, colored, and otherwise formatted text.
The TextBox control is similar to its Windows Forms counterpart. One nice addition to the WPF version is an automatic spell checking feature, complete with a suggestions popup similar to the one provided by the RichTextBox.
A ToolBar displays a set of small buttons and other controls for quick access.
To give the user the full ToolBar experience, place one or more ToolBars inside a ToolBarTray. The ToolBarTray arranges the ToolBars and lets users drag them around. Place Buttons and whatever else you need inside the ToolBars.
If you have multiple ToolBars, you can set their Band properties to indicate which horizontal band should initially hold them in the tray.
The ControlSamples program shown in Figure 2 defines two ToolBars in bands 0 and 1.
As you can probably guess, the ToolTip displays a tooltip. The easiest way to use a ToolTip is to set another control’s ToolTip property to the text that you want the ToolTip to display. For example, the following code sets a Button’s ToolTip.
If you want a ToolTip to do something more creative than simply displaying text, you can set a control’s ToolTip property as an attribute element, and place a single child inside the ToolTip. If you like, the child can be a container that holds several controls.
The following code makes a Button’s ToolTip use a TextBlock with word wrapping.
The TreeView displays hierarchical data in a tree-like format similar to the one used by Windows Explorer. The TreeView should hold TreeViewItems with Header properties set to the data that you want to display. For simple textual data, you can set the Header property to the text you want displayed. To display something more complicated, you can create the Header property as an attribute element.
To make a branch within the data hierarchy, simply place a TreeViewItem inside another TreeViewItem.
The following code shows how program ControlSamples makes the Physics branch of its TreeView. The Physics item contains two sub-items. The first simply says “Falling.” The second displays a horizontal StackPanel containing a TextBlock and an Image.
WPF also allows you to bind a TreeView to a data source so it can build its display on the fly. That’s more complicated, so I’ll defer it to a later article.
The UniformGrid arranges its children in a grid where every cell has the same height and width. It places its children in the cells in the order in which they are added to the grid, so you don’t need to specify each child’s row and column.
You don’t need to specify the row heights or column widths either. You simply set the control’s Rows and Columns properties to tell it how many rows and columns to make and it divides its area up accordingly.
ControlSamples‘ UniformGrid is orange and in the upper right corner.
The Viewbox displays a single child control resized and stretched in various ways. The control’s Stretch property (which can take the values None, Fill, Uniform, and UniformToFill) determines how the child is stretched. See the section earlier on the Image control for information about these values.
The ControlSamples program uses the following code to display a Label that’s stretched vertically.
The WindowsFormsHost can hold Windows Forms controls. For example, you could use one to display a DateTimePicker, which has no WPF equivalent.
Unfortunately using the WindowsFormsHost isn’t completely trivial. You need to perform three steps before you can use the control.
First, add a reference to the WindowsFormsIntegration library. In Visual Studio, you’ll find it in the .NET references tab. In Expression Blend, you’ll have to browse to find it. On my system it’s here:
C:Program FilesReference Assemblies MicrosoftFrameworkv3.0 WindowsFormsIntegration.dll.
Second, add a reference to the System.Windows.Forms.dll library. Again Visual Studio lists it on the .NET references tab and you have to browse to find it in Expression Blend. On my system it’s installed here:
Third, add a namespace similar to the following at the top of the XAML file.
Now you can display the control using XAML code similar to the following.
Note that neither Expression Blend nor Visual Studio do a great job of crossing the WPF/Windows Forms boundary at design time. They tend not to display the Windows Forms control inside the host and they may not calculate the host’s size correctly if it depends on the size of its contents.
The WrapPanel lays out its children in a row or column much as a StackPanel does but with one main difference. When a StackPanel runs out of room, it stops displaying its children: all “overflow” children are clipped. When a WrapPanel runs out of room, it starts a new row or column and keeps going.
The WrapPanel on the right of Figure 2 displays five Labels with various widths and heights. It places the first three on one row, runs out of room, so it creates a new row to hold the last two Labels.
Control Your Destiny
As you’ve seen, WPF provides a lot of controls, some that should seem familiar from Windows Forms and some that are completely new. This article contains enough information to let you know what each control does and how to get started using it, at least in straightforward ways.
You’ll still probably need some practice using the controls to get the hang of them. It takes a while to figure out which combination of Grids, StackPanels, and other controls you prefer for building user interfaces.
There are also plenty of properties, methods, and events that this article doesn’t even mention. Even the simplest controls have dozens of properties that you’ll need to learn to use.
For more information about the WPF controls, check the WPF Control Library web page. Meanwhile, download the examples and take a look at the code for yourself.