Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.

Channels ▼


Embed Custom GUIs in WPF

Eric has developed everything from data-reduction software for particle bombardment experiments to software for travel agencies. He can be contacted at [email protected]

Windows Presentation Foundation (WPF) is the graphics and user interface engine that debuted in .NET 3.0. WPF's FlowDocument class lets you easily manipulate documents containing rich content. FlowDocuments can be displayed in FlowDocumentReaders and FlowDocumentPageViewers, and are editable, with built-in spellcheck, if they're nested in RichTextBox controls. FlowDocuments can include all the content you'd expect—text, graphics, bullet and numbered lists, tables, and even hyperlinks. Additionally, since FlowDocuments can contain objects derived from the UIElement class, interactive GUIs can be embedded in FlowDocuments—buttons, radio buttons, custom controls, and user controls, for instance. (When embedding GUIs in RichTextBoxes, set the IsDocumentEnabled property to True.)

Unfortunately, WPF 3.5 does not fully support custom GUIs in FlowDocuments. In particular, drag-and-drop, cut-and-paste, deserialization, and printing require extra coding for full-fledged embedded GUI support. In this article, I show how to insert UserControls in FlowDocuments to make deserialization, clipboard operations, and printing work. I've included the full source code for two applications that demonstrate the issues—and workarounds—with embedded GUIs (available online; see "Resource Center," page 5). To use the code, load WPFCompoundDocuments.sln in Visual Studio 2008 or Visual C# 2008 Express Edition, and build and run the User Control Demo program (Figure 1). The User Control Demo illustrates the problems with UserControls in FlowDocuments.

Before pressing the Insert UserControl button, type some text in the RichTextBox on the left. Press Serialize and the document's contents are serialized to a string. Then press Clear and Deserialize, and you see the document's text restored. So far, so good. Now press Insert UserControl, Serialize, and Deserialize. When you press Deserialize, a XamlParseException is thrown, with this message:

[Click image to view at full size]

Figure 1: User Control Demo program.

Cannot set Name attribute value "timestampTextBlock" on element "TextBlock". "TextBlock" is under the scope of element "TimeStampControl", which already had a name registered when it was defined in another scope.

One solution to this problem is to not use a Name attribute for any child element in a UserControl's XAML markup. However, for all but the simplest UserControls, this would require too much effort. For example, the PhotoControl (see PhotoControl.xaml and PhotoControl.xaml.cs) manipulates several XAML elements by name (for instance, slideShowCheckBox, displayImage, imageListBox, and so on). The XAML element names could be removed, and each element could be searched for in the control's XAML markup, but there's a better solution. Keep reading!

Now try to copy-and-paste. Press Clear and press Insert UserControl. A TimeStampControl is inserted. Right-click TimeStampControl and select Copy. Notice that the UserControl's markup does not appear in the selection's markup in the Details window. Press Clear and right-click RichTextBox and select Paste. Oops! No UserControl is pasted because it was filtered out of the selection before it was copied to the clipboard. Fortunately, each of these issues can be handled without too much code. To see the workarounds in action, run the WPF Compound Documents app (Figure 2).

The WPF Compound Documents app can deserialize, copy/paste, and print UserControls. Here's how it works.

[Click image to view at full size]

Figure 2: Workarounds in action.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.