Text and Fonts
Silverlight provides several elements for rendering text, along with a set of properties for creating a variety of formatted text.
This topic contains the following sections.
- Text Elements
- Specifying Text and Font Properties
- Silverlight Fonts
- Colors and Brushes for Text Foreground
- TextBlock Text Model
- TextBox and PasswordBox
- RichTextBlock and RichTextBox
- Other Text-Related Controls
- Handling Keyboard and Text Events from Text Elements
- Related Topics
Broadly speaking, a text element in Silverlight is one of the following:
Certain control-specific types, such as DataGridTextColumn.
These elements share the characteristics of having a set of properties that control how text displays in the element or the element's content. These properties are: FontFamily, FontSize, FontStretch, FontStyle, FontWeight, and Foreground. The implementation of the properties is not necessarily shared between the elements as part of a common inheritance, but the implementations are similar in each text element.
The TextBlock object is the primary element for displaying read-only text in Silverlight-based applications. The following XAML shows how to define a TextBlock element and set its Text property to a string.
<TextBlock Text="Hello, world!" />
The following illustration displays the result of the previous XAML.
TextBlock also supports a basic text model for its content, which is discussed in the "TextBlock Text Model" section of this topic.
TextBlock is not the only Silverlight UI element that directly displays text. RichTextBlock, TextBox, PasswordBox, and RichTextBox are also text elements. These classes derive from the Control class, which implements a number of properties that are relevant to text and fonts. However, it is not always true that a class that derives from Control is capable of displaying text, or even supports a content model that can contain a text element. The following is a list of the relevant text and font properties that are implemented on the Control class:
Font Property Inheritance in Text Controls
One reason why the text and font properties are implemented at the level of Control is so that controls can support property value inheritance for font properties. This makes it possible to define a control with composite parts that come from a template, and to have the font properties of the parent control apply to any of the composite parts or content that display text strings.
For example, a ComboBox is an items control that might display other elements, or might display text. If you set font properties on ComboBox, the font properties are automatically inherited by the other elements or by the displayed text (without requiring any special handling by the control's logic). For displayed text, inheritance of font properties is particularly useful because there would not be a way to apply attributes to that text. Composite parts and text content in a custom control can inherit its Control-based font properties in exactly the same way.
Property inheritance of font properties works when the composite part is a TextBlock. This is true even though TextBlock is not technically a control and does not share the property implementations with its parent. That is one reason why the font properties between controls and TextBlock are parallel.
If you set text element properties through a Style or an applied template, child elements inherit the properties at run time. Run-time changes to text element properties also propagate their new values to inheriting child text elements.
Specifying Text and Font Properties
When using text elements, you can specify various font attributes of text elements in XAML, which parallel the properties available in that element's class. The following table lists the font attributes that you can specify for each of the text elements.
Specifies the desired font family, such as "Times New Roman".
The default value is "Portable User Interface", which is described in the "Supported Local Fonts" section of this topic. FontFamily can include a URI string that references a font file (and a family within the file, separated by a # character). This is for a case where rather than using fonts on the user system, you distribute the font file as part of your application's primary assembly. For more information, see FontFamily.
Specifies the desired font size in pixels. The values must be non-negative.
Specifies the desired glyph width of the font.
The default value is Normal. The effect of FontStretch is dependent on the specific font family being used, and can only specify fonts that already exist in a font family. It does not cause programmatic stretching of glyphs. (Note: you might consider applying a transform to the text if a FontStretch mapping is not available.)
Specifies whether the desired font style is normal or italic.
The default value is Normal. The effect of FontWeight is dependent on the specific font family being used, and generally only can specify fonts that already exist in a font family. Silverlight does not programmatically create a shear transform to simulate italics.
Specifies the desired glyph weight of the font.
The default value is Normal. The effect of FontWeight is dependent on the specific font family being used, and generally only can specify fonts that already exist in a font family. Silverlight does not programmatically create alternative weights, except when a family contains a normal weight font, but not a bold weight font. In this case, Silverlight will simulate a bold weight font by increasing the width of strokes using a 2D graphic algorithm.
Specifies one type of possible decoration, an underline.
The default is no decoration. To specify the underline decoration, set the TextDecorations attribute to Underline. TextDecorations is available as a property on TextBlock and inlines, but not available on Control-based text elements.
The following XAML shows how to define a TextBlock element and specify all of the font attributes listed in the previous table (excepting TextDecorations).
Depending on the font that Silverlight selects, the specified font attributes may not be the ones that are used during rendering. For more information, see the "Font Selection" section later in this topic.
<TextBlock Text="Font Attributes" FontFamily="Verdana" FontSize="36" FontStretch="UltraExpanded" FontStyle="Italic" FontWeight="ExtraBlack" />
The following illustration displays the result of the previous XAML content example.
The fonts you can use on your client computer in Silverlight depend on the version of Silverlight. In Silverlight 4, you can use any font on your client computer for any text element.
For a list of fonts supported in Silverlight for Windows Phone, see Fonts in Silverlight for Windows Phone.
In Silverlight 3, you can use a subset of the fonts on the client computer. The text elements in Silverlight 3 can use the following Latin fonts if available on the local computer.
Arial Unicode MS
Comic Sans MS
Lucida Grande/Lucida Sans Unicode
Times New Roman
Lucida Grande and Lucida Sans Unicode are aliases for the same font and are specified as a pair for compatibility reasons. Portable User Interface is a composite font. It uses several fonts to implement the range of international languages supported by Silverlight. This includes "Lucida Sans Unicode" and "Lucida Grande" for many Western writing systems, and many more for East Asian writing systems.
If you want to work with East Asian text, text elements in Silverlight 3 can use the following East Asian fonts if available on the local computer:
Text elements in Silverlight 3 on computers running Microsoft Windows can also use the following East Asian fonts if available on the local computer:
MS UI Gothic
Text elements in Silverlight 3 running on Macintosh computers can also use the following East Asian fonts if available on the local computer:
Hiragino Kaku Gothic Pro
The font that you specify may not necessarily be the font that Silverlight uses. Silverlight chooses the font from the supported local fonts, from the fonts provided in a packaged file referenced in the FontFamily property, or from the stream-based zip or .ttf file passed to the FontSource property. The displayed result is the best match based on the values of the FontFamily, FontStretch, FontStyle, and FontWeight properties. It is important to specify all four of these font properties to make sure that an accurate and consistent font selection is made for your text element.
Specifying Non-Default Fonts
Silverlight does not include any fonts in its installation package, it relies on local system fonts for its defaults. If you want to use a font for a text element that is not on the list of supported local fonts, you can specify the font in XAML by using the FontFamily property, or in code using the FontSource property. The FontFamily property can specify a single font file or a zip file containing font files, and can incorporate a fallback sequence. Any font file referenced for a XAML FontFamily usage must be embedded within an assembly as a resource. When using FontSource, your code can load the source font file for the font (or a zip of fonts) from a stream such as isolated storage, or from XAP packaging.
Colors and Brushes for Text Foreground
The Foreground property enables you to specify a Brush for the rendered text. The following XAML shows the simplest usage for Foreground, which is to use a named color string that applies a SolidColorBrush of that color to the text. Notice that Foreground is set separately on TextBlock and on each of the Run text elements within it.
<!-- TextBlock with different brushes applied to parts of the text. --> <TextBlock FontFamily="Verdana" Foreground="Navy"> Navy <Run Text="DodgerBlue " Foreground="DodgerBlue"/> <Run Text="LightSteelBlue " Foreground="LightSteelBlue"/> </TextBlock>
A solid color is not the only way to apply a foreground to a font. You can use any of the Brush derived classes in Silverlight, including RadialGradientBrush, LinearGradientBrush, ImageBrush and VideoBrush. If you specify these brushes in XAML, you must use property element syntax, or use a reference such as a resource reference. The following XAML shows an example of using property element syntax and specifying an ImageBrush for text:
<TextBlock Text="SHRUBBERY"> <TextBlock.Foreground> <ImageBrush ImageSource="forest.jpg"/> </TextBlock.Foreground> </TextBlock>
The following illustration shows the rendered text from the previous XAML.
TextBlock Text Model
Using the Run and LineBreak Objects
Instead of displaying a single string, a TextBlock can also display a series of strings contained in different Run elements, where each element can have different character-level formatting. The LineBreak object represents an explicit new line in a TextBlock, and is generally used between surrounding Run elements. LineBreak and Run share a base class (Inline), which makes it possible for a TextBlock to hold a strongly typed InlineCollection of its text model content. That InlineCollection is also the TextBlock XAML content property, and the end result is that to specify items in the TextBlock model you simply specify various Run and LineBreak elements as child elements of the TextBlock.
<!-- Display formatted text as Run objects within a TextBlock. --> <Canvas> <TextBlock FontFamily="Arial" Width="400" Text="Sample text formatting runs"> <LineBreak/> <Run Foreground="Maroon" FontFamily="Courier New" FontSize="24">Courier New 24</Run> <LineBreak/> <Run Foreground="Teal" FontFamily="Times New Roman" FontSize="18" FontStyle="Italic">Times New Roman Italic 18</Run> <LineBreak/> <Run Foreground="SteelBlue" FontFamily="Verdana" FontSize="14" FontWeight="Bold">Verdana Bold 14</Run> </TextBlock> </Canvas>
The following illustration shows the rendered formatted text from the previous XAML.
TextBlock rendering multiple Run objects
LineBreak forces the text in each Run to display on a separate line. Without the LineBreak, the text in each Run would flow together as one line and would often be clipped due to exceeding the TextBlock object width or the width of the Silverlight content area. The following illustration shows how the formatted text would render without using LineBreak objects.
Accessing the TextBlock Text Model in Code
There are really two properties involved in the TextBlock text model: Text, and Inlines. Changing the value of Text at run time is not recommended, because it can flatten any existing font element formatting on the individual Run items as well as strip the LineBreak elements for a TextBlock that was originally constructed with inlines and not just Text. For more information, see Inlines.
The TextWrapping property declares how text should wrap in a TextBlock. By default, text in a TextBlock does not wrap. With no wrapping, one of two things might happen to the text, depending on other settings:
If the TextBlock does not have an explicit Width set, the TextBlock expands based on the size of text within it, updating the value of ActualWidth. However, a TextBlock is always within some other container parent, and somewhere up the chain of layout parents there is inevitably a width constraint. This will result in the text being clipped if it exceeds the acting layout constraint width.
<TextBlock Text="The quick red fox jumped over the lazy brown dog." TextWrapping="Wrap" />.
Text wrapping exhibits the following behavior:
You can detect clipped text programmatically because ActualWidth for a TextBlock always reports the expanded size of the text, even if it does not fit in the layout container. If you know where to read the Width for the layout container that is doing the clipping, you can compare these two values.
The following illustrations show text wrapping behavior.
Multiline TextBlock Text
Either due to wrapping or to explicit LineBreak elements, the text in a TextBlock is potentially multiline text. Two properties of TextBlock affect how multiline text displays: LineHeight, and LineStackingStrategy. LineHeight sets the height of every line of content in the overall TextBlock. LineHeight is truly the baseline to baseline height, so if you set a LineHeight that is smaller than the FontSize, your text might be cut off in the vertical dimension. Typically, you leave LineHeight unset, and rely on a default behavior that renders an effective line height based on FontSize plus an offset. LineStackingStrategy affects that default algorithm if it is used. LineStackingStrategy.MaxHeight (the default) bases the effective line height on the maximum height of any character in the font. LineStackingStrategy.BlockLineHeight bases the effective line height on the "block" font design measure that is also stored as a value in the font.
Applying Transforms to TextBlock Text
Transforms can alter the display of text in your application. Transforms can be applied to many different UI elements, including text elements. One scenario where you might use transforms on text is so that you can animate the transform, for a visual effect. The following are some transforms you might use for text:
RotateTransform to invert text.
ScaleTransform for larger text than the maximum size supported inherently in the font.
SkewTransform for shearing or italics simulation.
TranslateTransform for offsets and shadow effects.
When you apply transforms to text, you should first consider whether there is another way to obtain the same or similar results using a specific text element property. For example, if a font family supports an italic FontStyle, the result is more visually appealing than applying a SkewTransform.
Animating TextBlock Text
The value of many text properties can be animated including the text size of FontSize, position through a TranslateTransform, and color. For more information about animation that applies to animating text elements and their properties, see Animation Overview.
Animating properties of text (particularly size or the foreground brush) can potentially use a lot of system resources. This is because when Silverlight renders text, it uses hinting to smooth each text glyph. If you animate the text size (by using a Transform or FontSize), Silverlight will hint the glyphs for each frame, which is costly and could cause frame dropping. If your application requires dynamic scale changes of large text, it may be better to use one of the following two alternatives:
TextBox and PasswordBox
Silverlight includes a TextBox control, and the derived PasswordBox control, in its core control set. A TextBox is typically used to capture text input from a user. A PasswordBox is typically used for authentication scenarios. The primary difference between these controls is that characters typed in a TextBox are displayed and characters typed in a PasswordBox display are masked.
When a TextBox has keyboard focus or when the mouse pointer is moved over it, the cursor typically changes to an IBeam. This behavior is based on the default templates and can be changed on a per-instance basis.
Wrapping TextBox Text
The TextBox control supports text wrapping. By default, the TextWrapping property is set to NoWrap. Without text wrapping, if the entered text exceeds either the explicit Width or a width constraint imposed by a parent layout container, the text will scroll such that the cursor always remains in view. If you set TextWrapping to Wrap, then the text does not scroll horizontally and wraps within the TextBox. It is still possible to produce a situation where input text is not visible, if the Height or effective render height of the TextBox is exceeded.
Multiline TextBox Text
TextBox can potentially support multiline text, if you set AcceptsReturn to true. In this mode, the ENTER/RETURN key is recorded as a new line. Any entered character for new line is potentially included in the Text or SelectedText values in this case.
TextBox Selection Model
TextBox includes several APIs that are related to any selected area of text:
The SelectedText property gets the selected text and is also potentially settable.
By default, you select text by dragging the mouse, or by holding down the SHIFT key and then pressing the ARROW keys. For this and other reasons, the TextBox control sometimes handles and suppresses some of the general input events, such as MouseLeftButtonDown, or KeyDown for specific keys. The specific keys are keys that that can move the cursor, such as the ARROW keys.
RichTextBlock and RichTextBox
Silverlight 5 introduces a RichTextBlock control that you can use to display rich text.
Other Text-Related Controls
This section describes other controls that relate in some way to displaying text.
Label is a control that displays content and can be associated with another control. Label derives from ContentControl and also can display text. Label has a Target property and automation support to associate it with another control that it references. Typically a Label just uses a string as Content, but it is possible to supply a container element for more control over the text formatting. Label is available in the Silverlight SDK client libraries.
AutoCompleteBox is a composite control that provides a TextBox for user input and a drop-down that contains possible matches based on the input in the TextBox. AutoCompleteBox has a Text property, but instead of exposing the various text element properties directly, it exposes a TextBoxStyle so that you can apply style setters that affect the TextBox composite part. AutoCompleteBox is available in the Silverlight SDK client libraries.
ItemsControl or HeaderedItemsControl have capabilities for displaying text items using content presenters. The text within the items is just text as a string, and does not support separate styling or a text object model. However, you can use the property value inheritance characteristic of the text element properties to set the values on the control parent, which then applies to the items text. ComboBox has similar capabilities (it is also an ItemsControl).
Popup is often used to display text, but it does not have a property that takes a string. Instead, it has a Child property that can take any UIElement. Typically you use a TextBlock as the Child value, set a Text value, and optionally style the text using the other TextBlock properties.
ToolTip uses the ToolTipService.ToolTip attached property for placement, and you can use a string for this value and not even include a ToolTip element in the XAML. Otherwise, you should specify a ToolTip object element as the ToolTipService.ToolTip property element value. For example, you can use a TextBlock and set its Text property.
Neither Popup nor ToolTip content will inherit font element properties, not even from the XAML page root element. This is because these objects are considered outside the general Silverlight visual tree when displayed, and the text element property values inherit from the visual tree. If you want to style the text within a Popup or ToolTip, set attributes or apply styles on an explicit TextBlock that you declare as content. Otherwise you will get the content presenter defaults for text, which are the same as the TextBlock defaults.
Handling Keyboard and Text Events from Text Elements
A very common task in a Silverlight application is handling keyboard input. Keyboard input is handled at a general level by two events that are implemented on UIElement: KeyUp and KeyDown. However, you often do not use these particular events for processing key or text input on specific text elements or text controls. Instead, you use control-specific events.
TextBlock is conceptually a read-only UI element, and users cannot directly change the text. You also cannot set the focus on a TextBlock, and focus on an element is necessary in order to originate any key events. For more information about the focus, see Focus Overview.
TextBox is intended for user input, can receive focus, and does originate key events. However, the TextBox class has class-level handling for KeyUp and KeyDown. This means that if you register event handlers for these keys, for example with the XAML <TextBox KeyDown="tb1_KeyDown" .../>, your handlers are occasionally not invoked because the TextBox class logic might mark the event handled before your instance receives it. This is part of the intentional design of the control. Some keys are not considered text and are instead considered specific to the control UI behavior. Therefore, the KeyUp and KeyDown keys do not raise TextChanged or SelectionChanged events.
If you encounter a scenario where you need to specifically handle KeyUp and KeyDown events for all key cases from TextBox or a derived class, you can still register a handler if you use the AddHandler method to attach the handlers.
KeyUp and KeyDown events are routed events. This means that if they are not handled by the TextBox, they can potentially bubble up the visual tree and invoke handlers on successive parent elements. For more information about the routed events in Silverlight, see Events Overview for Silverlight. For more information about keyboard events, see Keyboard Support.
Often a TextBox is used as part of a two-way data binding scenario. TextBox.Text is unique in that by default it updates the target only when the TextBox loses focus, to avoid data propagation on each user keystroke before the user is finished entering the text. For more information about two-way binding, update mechanisms, and validating data, see Data Binding.
The Glyphs class is also used to display text. Glyphs handles text at a lower level than TextBlock or TextBox. Glyphs is intended to treat each glyph in its text content as potentially a separate entity, with the ability to separately control block offsets and other characteristics. Instead of a Text property, Glyphs has a UnicodeString property. Glyphs has no working defaults, not even for font family or font size. The expectation is that users of Glyphs are packaging a font file subset for a FontUri value. In general, the model for Glyphs is most practical when using tools that output the types of low-level text information that Glyphs can consume.
Glyphs is not considered a text element for purposes of inheriting text element property values. None of the Glyphs properties align directly with the font element properties, such as FontFamily or FontSize, because of the different approach that Glyphs has towards text display.