Introduction
[ Back
To Top ]
Editor's Note: This article is written about Silverlight 2.0 Beta 1.
Topics covered in this article may change in newer versions of Silverlight.
With
the introduction of Silverlight 2.0 beta 1 at MIX08 in March, the infant
Silverlight platform took a big step forward. It now has rich support for data
binding. It has a vastly increased subset of WPF's UI engine. It even has
radical new technologies like Deep Zoom. But most importantly, Silverlight 2.0
beta 1 introduces a brand new collection of built-in UI controls.
The
new UI controls are not a surprise, but they are a key milestone in
Silverlight's maturation. Microsoft has always shipped platform technologies
with a collection of built-in controls, and beta 1 ushers in that era for
Silverlight. Developers evaluating the platform as an alternative to building
applications in ASP.NET or WinForms can now seriously consider it since it has
the beginnings of the complete UI productivity toolbox.
The
UI controls introduced in Silverlight 2 beta 1, though, are unique in many ways
from the controls that precede it. They are shipping with an unprecedented
licensing model (for Microsoft UI controls, that is) and are doing many things
with XAML controls that WPF has yet to produce (eh..hem…DataGrid). In this
article, we'll look at each of the 29 UI controls that ship in Silverlight 2
beta 1 and introduce you to their features, unique properties, and talk about
some of the shortcomings in the current versions of the controls.
Layout Controls
[ Back
To Top ]
Silverlight
2 beta 1 ships with three built-in layout controls: Canvas,
StackPanel, and Grid. Before
the beta release, Silverlight only provided a basic Canvas layout control, so
the addition of the new StackPanel and Grid greatly improve your ability to
flexibly (or precisely) control element position in your Silverlight
application. If you've done any Windows development (especially with WPF) the
"layout container" concept should be very familiar. If you're coming
from the ASP.NET world (like me), it takes a little more getting used to.
In
short, these layout containers help you position elements in your Silverlight
application so that you don't have to manually set absolute positions for every
element on your page. As your page is resized or as you add elements to your
page, the layout containers intelligently shift things around based on their
defined behavior- work you would have to do manually otherwise. Furthermore,
these layout containers can be nested and extended, so they greatly improve
your ability to build custom UI controls or more advanced auto-layout tools.
Canvas
The
Canvas layout control is the most basic, and it has been around since the very
first Silverlight versions. It provides the simple ability to absolutely
position child elements relative to the canvas' top left
corner. For example, let's say we have the following code (Listing 1) that adds
a simple TextBlock to a Silverlight canvas:
Listing 1 - Canvas usage
<Canvas>
<TextBlock Text="This is text on a blank canvas."
Canvas.Top="50" Canvas.Left="50" />
</Canvas>
When
this code is rendered by the Silverlight plug-in, we'll see our text positioned
50 pixels from the top of the page and 50 pixels from the left of the page
(Listing 2).
Listing 2 - Canvas with Textblock

The
same result could have been achieved by simply adding a TextBlock to the
default Silverlight UserControl (with no Canvas tag). That's because the
UserControl provides a surrounding default canvas that can be used for element
positioning if no other layout controls are used. All other layout controls are
positioned relative to this default container. But be careful! The default
container can only contain one element, so you'll almost always make a layout
control the first element in your UserControl.
If
I nest one canvas in another, the elements in each canvas will remain relative
to the top left of their direct parent. In other words, elements in a canvas
are not always absolutely positioned to the top left of the page.
If the origin of the canvas moves, so do the relative locations of the
contained elements on the page. Listing 3 illustrates this with a second canvas
(colored red for clarity) added to first, but shifted 75 pixels down and to the
right.
Listing 3 - Nested canvas
<Canvas>
<TextBlock Text="This is text on a blank canvas."
Canvas.Top="50" Canvas.Left="50" />
<Canvas Canvas.Top="50" Canvas.Left="50" Background="Red">
<TextBlock Text="This is text on a blank canvas."
Canvas.Top="50" Canvas.Left="50" />
</Canvas>
</Canvas>

Anybody
notice what's missing in the image in Listing 3? If you said the red background
that's "supposed" to be filling our second canvas, you're right. This
highlights an important nuance of the Canvas control: while it will allow you
to position items "in it", it won't automatically "expand"
its background to hold the fill color. By default a canvas has a height and
width of 0 and a transparent background. If we add height and width of 50 to
our second canvas, we now see its position on the page (Listing 4).
Listing 4 - Canvas with visible background

StackPanel
The
StackPanel enables you to easily position elements next to each other, both
horizontally and vertically. In the web world, this is typically the type of
layout implemented with HTML and CSS, where the next item on the page renders
right where the other one stopped. It's less precise than the Grid layout, but
much more flexible for scenarios where you may not know the user's resolution.
Let's
see it in action. If you add two simple rectangles to a Silverlight canvas, by
default they'll render overlapped (Listing 5). If a Stack Panel is used,
though, the elements will automatically render next to each other. You can
change the StackPanel's rendering mode by setting the Orientation
property to either Horizontal or Vertical (default). Listing 7 shows the same
rectangles in a StackPanel with Orientation set to Horizontal.
Listing 5 - Default positioning

Listing 6 - Position with a StackPanel

<StackPanel>
<Rectangle Width="100" Height="50" Fill="Red"></Rectangle>
<Rectangle Width="50" Height="25" Fill="Green"></Rectangle>
</StackPanel>
Listing 7 - Horizontal StackPanel

<StackPanel Orientation="Horizontal">
<Rectangle Width="100" Height="50" Fill="Red"></Rectangle>
<Rectangle Width="50" Height="25" Fill="Green"></Rectangle>
</StackPanel>
Grid
Sure
to confuse more than a few ASP.NET developers, Grid is not
a datagrid. It's another layout control, most directly comparable to the HTML
table. And as you would expect from a table-esque control, the Grid layout
control allows you to precisely position your page elements in rows and
columns. The Grid supports both fixed-width columns and "liquid"
columns that fill the available space. Listing 8 shows a basic Grid layout
control with 2 columns and 3 rows, with the second column set to a fixed width
and the first liquid.
Listing 8 - Basic Grid layout control
<Grid x:Name="gridLayout1" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="300"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="300"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
</Grid>
As
you can see from the code in Listing 8, the "*"
operator is used to define liquid dimensions in Silverlight. You can also
gather that Grids are defined by collections of ColumnDefinitions and
RowDefinitions defined in the XAML. Unlike HTML tables, though, content is not
directly added to the column/row definitions. Instead, new controls are added
within the Grid's opening and closing tags and are then positioned by setting Grid.Column and Grid.Row dependency
properties (both of which will default to 0). Listing 9 shows the new Grid XAML
with TextBlocks added to each cell.
Listing 9 - Grid with content

<Grid x:Name="gridLayout1" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="300"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="C1R1" Grid.Column="0" Grid.Row="0" />
<TextBlock Text="C2R1" Grid.Column="1" Grid.Row="0" />
<TextBlock Text="C1R2" Grid.Column="0" Grid.Row="1" />
<TextBlock Text="C2R2" Grid.Column="1" Grid.Row="1" />
<TextBlock Text="C1R3" Grid.Column="0" Grid.Row="2" />
<TextBlock Text="C2R3" Grid.Column="1" Grid.Row="2" />
</Grid>
Grids
also support a number of other advanced features, like column/row spanning (a concept
borrowed from HTML tables), auto spacing, and even proportional sizing. The
last feature is pretty cool because it allows you to set the width of a column
to, let's say, "3*" and the column will automatically scale in
proportion to the other columns (3:1 ratio). If only it were so elegant in
HTML!
Input Controls
[ Back
To Top ]
After
layout controls, some of the most essential controls in any "real
world" application are input controls. They are so common and so often
used that we tend to forget their essential utility until they are missing.
Such is the case with Silverlight 1.0, where even basic controls like buttons
and textboxes are absent. Fortuantely, Silverlight 2.0 beta 1 solves that
problem.
In
the current beta, there is a near complete collection of input controls,
including: Button, Calendar, CheckBox, DatePicker, ListBox, RadioButton, Slider, TexBox, ToggleButton,
and even a WatermarkedTextBox. While this is a great
start, the list is missing notable input controls common in other Microsoft
platforms like a dropdownlist/combobox, rich textbox, image button, and upload
control. While some of these may be added in subsequent betas, you can fully bet
the 3rd party component makers, like Telerik, will fill-in the gaps.
Most
of the new input controls included in Silverlight are fairly standard and will
feel just like their ASP.NET and WinForms counterparts. Nonetheless, let's take
a look at each so you can see what the markup looks like how each control
renders in the browser.
Button & ToggleButton
One
of the most basic and fundamental input controls is the button. Many
applications would be rendered useless without at least one button doing
something, so you'll probably end-up using this control (or controls derived
from it) a lot. Listing 10 shows the basic XAML
required to add a button to your Silverlight application and shows the default
rendering.
Listing 10 - Default button



<Button Width="80" Content="Push Me"></Button>
Notice
that the button's text is set via the Content property,
not a "Text" property. This change was made to reflect the concept
that a Button (or almost any Silverlight control) can render more than simple
text strings. You can render almost anything on a button, including images,
videos, and, of course, simple text- thus the generic "Content"
property. If you want to render more complex content to a button, you can use
the button's ContentTemplate, which allows you to add a
layout control to the button's content area and take full control of the
rendered output. This helps overcome the absence of controls like image
buttons. Listing 11 shows a more complex Silverlight button implementation that
uses the ContentTemplate to add a shape and some text to the button.
Listing 11 - Button ContentTemplate

<Button Width="150">
<Button.ContentTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Ellipse Fill="Green" Width="15" Height="15"
Grid.Column="0" Grid.Row="0"></Ellipse>
<TextBlock Text="Push Me" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Center"
Margin="5"></TextBlock>
</Grid>
</DataTemplate>
</Button.ContentTemplate>
</Button>
The
Button control, like most Silverlight controls, also provides a ClickMode property that lets you define when
a click event fires: mouse hover, mouse down, or mouse up. It's a new way for
web developers to think, but familiar territory for Windows developers.
Meanwhile,
the ToggleButton is simply a tri-state button control. That means it has a
normal state, a clicked state, and an in-between "toggled" state.
It's not very common in standard web applications, but the concept is simple to
grasp. All features of the regular Silverlight Button are supported by the
ToggleButton.
Calendar & DatePicker
A
little more complex than a basic button, the Calendar control serves the
universal purpose of helping users visualize and provide DateTime information.
And directly related, the DatePicker control simply takes a Calendar and
automatically attaches it to a Textbox so that it's easy for you to collect
date input. The Calendar/DatePicker in Silverlight more closely resemble the
rendering and features of an ASP.NET calendar than the terrible
default calendar than comes with WinForms, so this territory will be more
familiar for web developers than Windows developers.
The
Calendar control has a number of unique properties that customize the control's
behavior, including AreDatesInPastSelectable, DisplayDateEnd/Start, DisplayMode, FirstDayOfWeek, IsTodayHighlighted,
and SelectableDateEnd/Start. Most of these properties
expose their behavior through their naming, so little explanation is needed.
The Calendar control is not as full featured as most 3rd party calendar
controls currently available for other Microsoft platforms, but is a much better
"basic" starting point than Microsoft has provided in the past.
Listing
12 shows a basic Silverlight Calendar in both Month and Year DisplayModes. Also
shown is the Silverlight DatePicker in both collapsed and expanded states.
Listing 12 - Basic Silverlight Calendar


<Calendar DisplayMode="Month" FirstDayOfWeek="Monday"></Calendar>


<DatePicker Width="150"></DatePicker>
CheckBox & RadioButton
CheckBoxes
and RadioButtons are universally recognized, common in many applications, and
essential parts of the Silverlight UI control set. The Checkbox and RadioButton
in Silverlight very closely resemble their HTML/ASP.NET counterparts, both in
functionality and property naming. The controls share the Content
property for defining the elements that will be rendered next to the
checkbox/radiobutton and also share the IsThreeState
property. The IsThreeState property enables the CheckBox and RadioButton to
operate as tri-state controls, similar to the functionality of the
ToggleButton.
The
CheckBox has one unique property called IsChecked. Just
as in ASP.NET, this property enables you to programmatically set the checkbox's
selected state. Meanwhile, the RadioButton has the unique GroupName
property, which is used to define which radiobuttons will be toggled when a
selection is made. Listing 13 shows both of these controls and their default
rendering.
Listing 13 - Silverlight CheckBox and RadioButton



<CheckBox IsChecked="True" IsThreeState="True" Content="Checkbox" />
<RadioButton GroupName="rb" Content="RadioBtn1" />
<RadioButton GroupName="rb" Content="RadioBtn2" />
ListBox
The
ListBox control is a very flexible UI control in Silverlight that makes it easy
to display lists of data. It is similar to the ASP.NET ListBox, but much more
flexible thanks to Silverlight's XAML underpinnings that allow anything to be
rendered in each list item (via the ContentTemplate property).
The ListBox accepts a collection of ListBoxItems to define items, and it will
automatically render scrollbars if the content is larger than the ListBox
dimensions. Listing 14 shows the ListBox in action.
Listing 14 - Silverlight ListBox

<ListBox Width="150" Height="80">
<ListBoxItem Content="Item 1" />
<ListBoxItem Content="Item 2" />
<ListBoxItem Content="Item 3" />
<ListBoxItem Content="Item 4" />
<ListBoxItem Content="Item 5" />
<ListBoxItem Content="Item 6" />
</ListBox>
If
you are binding data to your ListBox control, you bing the collection to the ItemSource property (similar to the DataSource property on
ASP.NET controls). The collection can be anything that implements IEnumerable,
so the binding support is very flexible. You can also use the SelectedItem
and SelectedIndex properties to identify items that
users select.
Slider
Slider
is not a standard control in the ASP.NET developers default toolbox, though
many free and 3rd party implementations exist to fill the gap. With
Silverlight, the tool is built-in to the platform and immediately at your
disposal.
As
far as the implementation goes, it's a pretty standard control with support for
vertical and horizontal rendering, setting minor and major ticks, and setting
slider range values. The most serious missing "feature" is support
for the mouse scroll wheel, though technically, that's a Silverlight platform
problem (Silverlight doesn't currently support the scroll wheel, though
workarounds do exist). Hopefully future versions of the platform will fix this
problem. In the mean time, keyboard support abounds and the control's rich
event model will enable you to do a lot of fun things in the browser.
Listing
15 shows the default Slider control rendering. You can click and drag the
slider, click anywhere on the slider "bar", or use the keyboard to
change the slider's value.
Listing 15 - Silverlight Slider

<Slider IsDirectionReversed="True" Width="200"
SmallChange="10" LargeChange="20"
Minimum="0" Maximum="100" />
Some
of the Slider's unique properties are illustrated in Listing 15, such as
SmallChange, LargeChange, Minimum, and Maximum. The Min and Max properties
obviously set the value range that the slider represents, and the Change
properties dictate how many units the slider will move per interaction.
Clicking on the Slider track will trigger a "large" change; using the
keyboard will trigger "small" changes.
TextBox & WatermarkedTextBox
Controls
don't get much more basic than a TextBox (a rectangle that accepts text), and
Silverlight doesn't do much to innovate on the tried and true basic. There are
two flavors of TextBox in Silverlight 2 beta 1: regular and watermarked. Both
share the exact same feature set with the key exception that the
WatermarkedTextBox has an extra Watermark property.
The
only unique feature of the current TextBox is that it now supports line breaks,
so you can employ a simple multi-line textbox. Other than that, there is no
rich text editing support provided with the current textbox controls. This
could present a real challenge for web scenarios where developers are used to
working with formatted HTML.
Listing
16 shows both variants of the Silverlight textboxes and the required XAML.
Listing 16 - Silverlight Textbox and
WatermarkedTextBox

<TextBox Text="Some text" Width="200" />
<WatermarkedTextBox Watermark="Enter text" Width="200" />
Navigation Controls
[ Back
To Top ]
Your
users won't get very far if they can't traverse your application, and that's
where the Silverlight navigation controls come in to save the day. There are
only a couple of controls I consider "navigation" controls in the
current Silverlight 2 beta 1, though some of the Input controls we've already
looked at (like the button) could also be used for navigation. The controls
we'll look at in this section- HyperlinkButton, ScrollBar, and ScrollViewer-
can all be used to help users navigate through your
application or navigate your content. Let's see how they work.
HyperlinkButton
The
HyperlinkButton is a familiar carryover from the ASP.NET world and it serves
the primary purpose of making it easy to link to other URLs. The HypelinkButton
exposes all of the "standard" Silverlight button properties with one
key addition: the NavigateUri property. To use the
control, you can simply set this to a valid Uri and Silverlight will
automatically redirect you to that location. Listing 17 shows a simple implementation
of the HyperlinkButton. Notice that by default it renders in blue (standard
link usability on the web), but it does not underline
by default (hovered or unhovered). This is something you may want to address
manually to make your Silverlight application more user friendly on the web.
Listing 17 - Silverlight HyperlinkButton

<HyperlinkButton NavigateUri="http://www.google.com" Content="Click Me" />
The
NavigateUri property cannot be used to "navigate" to different XAML
pages in your Silverlight application. If you try to pass a relative XAML
location to this property (like, let's say, page2.xaml), Silverlight will throw
an exception.
ScrollBar & ScrollViewer
The
ScrollBar and ScrollViewer controls, unlike the Hyperlink, are familiar
carryovers from the WinForms world. The ScrollBar control provides a flexible
implementation of a scrollbar that you can use for any number of purposes, not
just scrolling content. In essence, it is Slider control with RepeatButtons
automatically rendered on either end of the track. The ScrollViewer, meanwhile,
is more focused on delivering support for scrolling content. It is actually
composed with ScrollBar controls internally, so it is not adding any new
scrolling features that the ScrollBar doesn't offer. In fact, the ScrollViewer
loses a few important features, like the ScrollBar's usefull Scroll event, so
make sure you pick the control that best suits your needs.
As
far as unique properties go, the ScrollBar exposes a few important properties
that enable you to control scrolling behavior. The properties are very similar
to those on the Slider control, such as Maximum, Minimum, LargeChange, SmallChange, and Orientation. The
purpose of these properties should be pretty self-evident- set a ScrollBar
value range, the size of ScrollBar steps when clicked (large steps occur when
the track is clicked, small steps when the buttons are clicked), and the
Horizontal or Vertical orientation of the ScrollBar. More interesting is the ViewportSize property. This property allows you to tell the
ScrollBar how much of the scrollable "content" is visible so that the
"thumb" (the movable scrollbar) can be sized appropriately. The
larger that you make the ViewportSize value, the wider the thumb will be.
The
ScrollBar also exposes two helpful events: OnScroll and
OnValueChanged. Both of these events allow you to
respond to user interaction with the ScrollBar and both are missing in the
ScrollViewer control by default. There are ways to "hack" these
events in to the ScrollViewer, and future versions may even expose these events
by default, but for now this is one of the key shortcomings of the ScrollViewer
control.
Listing
18 shows a basic ScrollBar control with a few of its "unique"
properties set. Notice that the width of the ScrollBar's thumb is wider than
default thanks to the value supplied to ViewportSize.
Listing 18 - Silverlight ScrollBar

<ScrollBar Width="200" Orientation="Horizontal"
Maximum="200" Minimum="1" ViewportSize="50"
LargeChange="50" SmallChange="1" />
Meanwhile,
the ScrollViewer control is specifically designed to enable scrolling of
content. Most Silverlight UI controls expose ScrollViewer dependency
properties, but you can also manually add a ScrollViewer to your application.
Since the ScrollViewer is dedicated to scrolling content, it does not provide
Minimum, Maximum, Large/SmallChange, or Value properties. Instead, it provides
Horizontal/VerticalScrollBarVisibility properties that can be set to one of
four values: Auto, Disabled, Hidden, or Visible. Listing 19 shows the
ScrollViewer in action with a TextBlock in the Viewer's content area.
Listing 19 - Silverlight ScrollViewer

<ScrollViewer Width="200" Height="50"
VerticalScrollBarVisibility="Visible">
<ScrollViewer.Content>
<TextBlock TextWrapping="Wrap"
Text="Some text in a TextBlock in the ScrollViewer" />
</ScrollViewer.Content>
</ScrollViewer>
Media Controls
[ Back
To Top ]
Navigation
and Input controls are essential to making any application work, but it is
usually the media controls that really give an application its visual appeal.
Silverlight provides a diverse array of media controls for displaying
everything from basic images to the snazzy Deep Zoom images. Let's take a look
at how Silverlight's UI controls enable us to display media in our beta
applications.
Image
How
do you display an image in a Silverlight application? With the Image control,
of course. And while you may be quick to dismiss the Image control as nothing
special (I did), there are some interesting properties on this control you
should be aware of, especially if you're coming from the web world. First, make
a mental note: Silverlight only supports JPEG and PNG images.
Sorry GIF purists, you're currently out of luck. If you try to use a GIF image
in Silverlight, an application exception will be thrown.
To
display an image, you need to set the Source property
of the Image control. The Source property can be set to one of two things: the
relative path to an image located in your Silverlight project or to an instance
of the BitmapImage class set in the code behind. If you try to set the source
directly to an image on the web (like, http://www.something.com/images/myimage.png)
Silverlight will crash. For scenarios like that, you can use the BitmapImage in
your code behind to build a new image based on a URI or stream.
Listing
20 shows a basic image control in a Silverlight application displaying an image
located in the Silverlight project. When the project is built, the image is
packaged in to the Silverlight XAP file (basically a ZIP archive with the
Silverlight specific .xap extension that represents a deployable Silverlight
application), so you don't have to worry about deploying your images separately
from your Silverlight application.
Listing 20 - Silverlight Image

<Image Stretch="None" Source="images/anxious.jpg"></Image>
Listing
20 also highlights another unique property of the Image control: Stretch. You can set this to one of four enumerated values:
None, Fill, Uniform, or UniformToFill. Clearly, "None" is the default
value and it renders an image in its original dimensions. The other values will
stretch the image, proportionally or not, to fill its parent container.
Also,
don't forget about some of the Image controls inherited properties, like Opacity. By setting this value to anything less than 1 you
can easily make your image translucent. Pretty cool! Now if only other image
transformations were so easy…Image.AutoCrop().FixColor().MakeInteresting().
Maybe in Silverlight 3.0.
MediaElement
While
the Image control is used for displaying static images, the MediaElement UI
control is your tool of choice for "displaying" audio and video clips
in your Silverlight app. It has a number of unique properties and events that allow
you to take control over your media and handle downloading/buffering. Going in
depth on these properties is an article unto itself, but at the highest level
you need to know that, like the Image control, the MediaElement exposes a
Source property that must be set to the URI of your content.
The
MediaElement only supports Windows Media Video, Windows Media Audio, and MP3 formats
(of varying flavors). The control also offers support for streaming if you're
using a Windows Media Streaming server and limited support for Advanced Media
Redirector (a.k.a. Windows Media metafiles) files. Neither of these extends
Silverlight's format support, but they give you more control over how you
distribute your media.
Listing
21 shows a basic MediaElement control hosting a sample Windows Media Video.
Unlike the Image control, videos won't automatically get packaged in to your
XAP file, which can cause some headaches when you first start playing with the
control. Instead, you need to manually copy your video files to the ClientBin
directory in your website for the MediaElement to find them (in the following
example, WindowsMedia.wmv is in the root of ClientBin).
Listing 21 - Silverlight MediaElement

<MediaElement Source="WindowsMedia.wmv" AutoPlay="True" Opacity=".7">
</MediaElement>
The
MediaElement also has support for Triggers. Triggers are essentially
"bookmarks," or "chapters," that you can define for any
media in the MediaElement. Typically you'd configure these ahead of time and
embed them in the media (with a program like Windows Media File Editor), but
you can create them dynamically be defining a collection of TimelineMarkers and
passing them to the MediaElement's Markers property.
Regardless of when they're created, each time a marker is reached during media
playback the MediaElement's MarkerReached event fires, giving you the
opportunity to create rich media playback environments.
MultiScaleImage
The
MultiScaleImage control is perhaps the worst named control in the current
Silverlight 2 UI controls collection. The control is really the required
front-end tool for taking advantage of Silverlight's new Deep Zoom technology
(formerly Sea Dragon in MS Labs). Deep Zoom enables you to display HUGE images
on the web in a ZUI (zoomable user interface) with smooth, animated transitions
that give the illusion of seamless image zooming.
Deep
Zoom images are created using a tool called, aptly, the Deep Zoom Composer. The
tool takes a large image (or multiple large images) and processes them in to
many smaller image "tiles" that are organized in number of folders.
Each folder represents a different "layer" in the final composition.
It is this collection of folders and image tiles that the MultiScaleImage
references and pieces together for you in your Silverlight application.
To
configure the MultiScaleImage, you simply set the Source
property to location of the .bin file generated by the Deep Zoom Composer.
You'll need to make sure you copy all of the folders to your ClientBin
directory (or wherever you chose to host your files) in addition to the .bin
file. In Listing 22, the .bin file is in the
"ToddPortrait1_vandalized" directory, which is in the root of
ClientBin and also contains all of the Deep Zoom generated content. If
everything is configured correctly, you should see your image "zoom
in" to view when your application loads.
Listing 22 - Silverlight MultiScaleImage

<MultiScaleImage Source="ToddPortrait1_vandalized/info.bin"
ViewportWidth="1.0" Width="300" Height="300">
</MultiScaleImage>
The
ViewportWidth property, set to "1.0" in
Listing 22, controls the MSI's zoom factor. The default value is 1, which means
the image will be displayed at a size that fits everything on the screen. The
closer the number supplied to ViewportWidth gets to zero, the more zoomed the
image will be. In other words, if we simply change the ViewportWidth to
".5" instead of "1.0," when the image loads it will be more
zoomed-in (Listing 23). You can also set numbers larger than 1, but as you do
the image will simply appear smaller on the page. A little backwards and
confusing, I know.
Listing 23 - ViewportWidth zoomed

You
can also set the ViewportOrigin property, which
obviously adjusts where the image is focused when it loads. That helps you
solve problems like the focus of the image above. There is also a UseSprings property that you'll discover on the MSI control.
This enables you to disable the Deep Zoom animations- a big part of what makes
the technology "sing"- so you'll probably rarely find a reason to set
this to false.
Advanced Controls
[ Back
To Top ]
So
far we've seen a lot of "basic" controls built-in to Silverlight's UI
control toolbox. Buttons, textboxes, hyperlinks, images, and the like are all
relatively basic controls that form the foundation of any application UI. What
we haven't seen are more advanced or complex controls
like a treeview, tabstrip, panelbar, scheduler, or the ever popular carousel.
As of Silverlight 2 beta 1, these controls simply aren't present and time will
reveal which get included by Microsoft and which will depend on the 3rd party
UI market to supply. For now, the only complex control in Silverlight is the
DataGrid, so let's take a look at how it works.
DataGrid
DataGrids
are fundamental UI controls for almost all line of business (LOB) applications.
They radically simplify the task of displaying structured data to users by
automatically handling the rendering of rows, columns, headers, and data
navigation. Silverlight's data grid is no exception. While it is far from being
a complete or "advanced" grid control by today's WinForms and ASP.NET
standards, it does provide basic grid functionality.
To
use the DataGrid control, you must simply bind the Grid to a list of items
(that implement IEnumerable) via the ItemSource property. In the simplest
approach, the Grid will automatically generate columns based on the data you
supply and even render "special" column types- like checkbox columns-
based on your data types. You can, of course, take more control and manually
define the columns that will be rendered in your grid by setting the AutoGenerateColumns property to false.
Listing
24 shows a simple Silverlight DataGrid that is bound to data supplied by a WCF
web service. The Grid is bound in the XAML page's code-behind by simply
supplying the list of items returned by the WCF web service to the Grid's
ItemSource property. Things to notice in listing 24 are the checkbox column
automatically generated for Boolean data and that the Grid has the built-in
ability to allow users to resize columns.
Listing 24 - Silverlight DataGrid

XAML
<my:DataGrid x:Name="dataGrid1" AutoGenerateColumns="true">
</my:DataGrid>
CS
void proxy_GetPeopleCompleted(object sender,
SilverlightControls.TestServiceReference.GetPeopleCompletedEventArgs e)
{
this.dataGrid1.ItemsSource = e.Result;
}
Unlike
all of the other UI controls you've seen so far, the DataGrid UI tag is
prefixed by the odd "my" name. That's because the DataGrid does not
exist in the default Silverlight namespace. You need to add the namespace in
Listing 25 to your XAML document in order to use the Silverlight DataGrid
control. The "standard" name you'll find assigned to this namespace
in most Silverlight demos is "my," but you could name this namespace
whatever you like (producing <whateveryoulike:DataGrid …).
Listing 25 - DataGrid namespace
xmlns:my=
"clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
The
DataGrid already exposes a number of properties that enable you to customize
its appearance and behavior. Among the most significant are AlternatingRowBackground,
CanUserResizeColumns, GridlinesVisibility,
HeaderVisibility, RowBackground,
and SelectionMode. That last property, SelectionMode,
allows you to control how rows can be selected. Setting the value to
SingleFullRow will only allow one row to be selected at a time; setting it to
ExtendedFullRow allows users to select multiple rows by using the shift and
control keys.
DataGrid Shortcomings
While
the DataGrid in Sivlerligth 2 beta 1 is a great addition to the framework, it
is still a far, far cry from providing the level of functionality we as
developers have come to expect from datagrid controls. For example, the current
DataGrid provides no out of the box support for sorting, grouping, filtering,
or hierarchal data display. Paging isn't even a supported concept as all data
is currently rendered and then scrolled (as is usually done in WinForms). Since
Silverlight is going to attract web developers, I expect many will view this
approach to paging as a shortcoming, too.
Data
editing is another soft spot. The Grid does support basic inline editing, but
advanced modes like form editing and pop-up window data editing are absent. For
Windows developers, this probably isn't a problem; for web developers, this is
another road block. That is a repeating theme in Silverlight that could pose
problems for both Microsoft and UI component vendors that build for
Silverlight. What type of developer do you try to please: traditional web
developers migrating towards richer web experiences or traditional WinForms
developers trying to build apps that can be distributed via the browser? Each
group has vastly different expectations of how UI controls should behave, so it
will be interesting to see which UI concepts win-out in Silverlight.
Everything Else
[ Back
To Top ]
At
the end of the day, there are a few controls that don't cleanly fit in to the
other categories. Call these controls "utility" controls or
"bonus" controls or whatever you like, but this wouldn't be a complete introduction of all Silverlight 2.0 controls if we
didn't briefly give them some attention.
ToolTip
ToolTip,
while basic, is a neat little utility control that allows you to attach
attractive ToolTips to just about anything in a Silverlight application. And
since they're provided by the plug-in (and not the browser), you have the
ability to take complete control over their styling and content. Listing 26
shows a simple ToolTip attached to a TextBlock providing users context when
they hover over the element.
Listing 26 - Silverlight ToolTip

<TextBlock Text="Howdy Silverlight" control:ToolTipService.InitialShowDelay="500">
<control:ToolTipService.ToolTip>
<ToolTip HorizontalOffset="10" VerticalOffset="10"
Content="Here's a tip..." />
</control:ToolTipService.ToolTip>
</TextBlock>
Normally,
a TextBlock doesn't expose a ToolTip property (like, say, a Button does).
That's where the ToolTipService comes in to play (seen
in Listing 26). Aside from giving you control (in milliseconds) over InitialShowDelay, ShowDuration, and BetweenShowDelay (as in, how long until the tip is displayed
again), the ToolTipService also enables you to attach ToolTips to objects that
don't expose them by default. To use the ToolTipService in Silverlight 2 beta
1, though, you'll need to add an extra namespace reference to your XAML page
since the Service is not built-in to the core Silverlight assembly (unlike
ToolTip). Listing 27 shows you the code that you need to add to your page.
Listing 27 - ToolTipService namespace reference
xmlns:control="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
You
may have also noticed in Listing 27 the HorizontalOffset and VerticalOffset
properties. These properties specify the offset distance in pixels relative to
the cursor, not the control. At present there is no
way to change other aspects of the tip's display, such as making the position
relative to the object vs. the mouse or making the tip display on the left vs.
the right. You'll have to wait for 3rd party controls to give you that level of
control (for now).
TextBlock
Equivalent
to the ASP.NET Label control, the TextBlock is your run of the mill read-only
text control. Like the Silverlight TextBox, it
exposes a Text property that enables you to set its
contents (vs. the more common Content property). Beyond that, there is nothing too special about the TextBlock and you should find it very
easy to use. Listing 28 shows the TextBlock "in action"- very dull
action.
Listing 28 - Silverlight TextBlock

<TextBlock Text="Howdy Silverlight"></TextBlock>
The
only other properties worth mentioning are TextWrap, LineHeight, and LineStackingStrategy,
all of which are somewhat related. When TextWrap is set to "Wrap"
(NoWrap is default), Silverlight will start wrapping text on to multiple lines when
it is longer than the controls defined width. And don't expect Silverlight to
look for word breaks- it will wrap in the middle of a word if that's where the
length constraints hit. In any event, when Silverlight wraps, by default it
will set a line height that accommodates the text and stack each line with no
overlap.
If
you want more control, you can manually set the LineHeight and then set the
LineStackingStrategy to one of two values: MaxHeight or BlockLineHeight.
MaxHeight closely imitates the default settings in that it won't allow text to
overlap, even if you've set a smaller LineHeight. Changing the
LineStackingStrategy to BlockLineHeight, though, will allow text to overlap
giving precedence to the LineHeight setting. Listing 29 shows two identical
TextBlocks with LineHeight set to 10. The only difference is the
LineStackingStrategy property, and you can clearly see the impact on text
positioning. In the design world, we call this type of "line spacing"
leading.
Listing 29 - LineStackingStrategy

<TextBlock Text="Howdy Silverlight" TextWrapping="Wrap"
LineStackingStrategy="<span class=Bold>MaxHeight</span>" Width="50"
LineHeight="10" />
<TextBlock Text="Howdy Silverlight" TextWrapping="Wrap"
LineStackingStrategy="<span class=Bold>BlockLineHeight</span>" Width="50"
LineHeight="10" />
Border
Border
is another poorly named Silverlight UI control. With its current name, it is
easy to think of it as some kind of "extension" control that enables
you to add borders to other controls (like rectangles or TextBoxes). In
reality, it is a control that enables you to draw boxes in your Silverlight
application, similar to HTML fieldsets (a better name in my opinion). The
Border control is actually a lot like the HTML fieldset because it also allows
you to add other Silverlight controls directly to its contents. This is a much
more convenient way to wrap elements in a box than trying to manually position
everything in a rectangle on your page (the alternative approach).
Listing
30 shows a Border control with a simple TextBlock contained. Note the CornerRadius property set in the example. This property makes
it very easy to round the corners of your Border box. It's a much more direct
approach than the RadiusX and RadiusY properties supplied by the XAML
rectangle, though clearly less configurable.
Listing 30 - Silverlight Border Control

<Border BorderThickness="3" BorderBrush="Black" Width="200"
Height="100" CornerRadius="20">
<TextBlock Text="I'm in a 'Border'" />
</Border>
Shapes
Since
Silverlight is based on XAML, you'll find it a lot easier to do basic drawing
and manipulation of shapes that you do in the GDI+ worlds of ASP.NET and
WinForms. Silverlight defines a number of simple shapes, such Ellipse,
Rectangle, and Line. Shapes can be almost infinitely styled, so it's up to you
and your imagination (and mastery of XAML…or Expression Blend) to make Shapes
work for you. Listing 31 shows a simple Rectangle with a solid brush fill and
an Ellipse with a gradient brush with the required XAML. How many lines of code
would it take to do this with GDI+ in ASP.NET? A lot more.
Listing 31 - Silverlight Shapes

<Rectangle Fill="Red" Width="200" Height="100" />
<Ellipse Width="100" Height="50">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="LightGreen" Offset="0" />
<GradientStop Color="Black" Offset=".5" />
<GradientStop Color="White" Offset=".8" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
The Future of Silverlight UI Controls
[ Back
To Top ]
Silverlight
2 beta 1 has introduced a lot of essential UI controls to the infant web
platform, but there is much more that needs to be done to make Silverlight
"complete." From a more complete collection of built-in controls to a
robust and functioning 3rd party market, Silverlight has some work ahead of it
to become an equal peer among stalwarts like WinForms and ASP.NET. There are
three key areas in Silverlight's UI component model that need improvement: More
advanced controls, 3rd party support, and better data access support.
Advanced Controls
While
the first beta of Silverlight 2 does ship with a DataGrid control, it is
lacking many of the other "complex" controls that are required to
build complete line-of-business (LOB) apps. Controls like treeviews, tabstrips,
menus, rich text editors, and schedulers are all absent in the current preview.
Some of these controls may be added by Microsoft in the next two betas, but if
history is any indication, there will be gaps in Microsoft's effort.
Part
of the challenge with Silverlight and its requirement to provide vast
collection of controls is that it is trying to appeal to two distinct developer
groups: Windows developers that want to build their apps for the web and web
developers that want more rich "desktop-like" experiences in their
web apps. Each group is used to a different "default" collection of
controls, so it is going to be very hard for Microsoft to please everyone. All
the more reason the next point is important.
3rd Party Support
Every
successful Microsoft development platform has been such due in part to rich 3rd
party support, especially in the UI control arena. Microsoft recognizes that it
can't (and doesn't want) to please everyone and they rely on the symbiotic
relationship with component vendors to address the needs of a diverse
development community. Silverlight is no exception.
As
Silverlight moves past its first beta and approaches RTM near the end of summer
2008, UI component vendors (like Telerik, DevExpress, etc.) will start to ship
complete toolboxes of controls built for the new platform. And while it's good
to know that's coming, production versions of 3rd party UI controls are still
months away. It's an important consideration to keep in mind when debating any
Silverlight development this year. Just imagine how productive you'd be without
your favorite UI component set in your current WinForms/ASP.NET projects!
Data Access Support
Finally,
Silverlight has a long way to go to make data access a more intuitive process.
Silverlight beta 1 has none of the traditional "data source" controls
we've grown to expect in Microsoft's development platforms, so building a
"quick" proof-of-concept Silverlight application that accesses a SQL
Server database is no trivial task. At present, it requires (at least) a web
service to serve the data from your web server to your Silverlight application
running in the browser.
There
are solutions on the horizon, like the Astoria project, that promise to ease
the pain, but Microsoft has no published plans to add data source controls to
Silverlight (or WPF, for that matter). Some Microsoft insiders have blogged
about the possibility of data source controls in the
future, but at this point it's nothing more than ideas. The only way to ensure
Microsoft spends enough time on this problem is if they get clear feedback from
the community- a.k.a. you! If you want data access in Silverlight to be easier,
let Microsoft know.
Conclusion
[ Back
To Top ]
Phew!
If you've made it this far you are now a virtual expert on the controls
included in Silverlight 2.0 beta 1. Hopefully you've found this information
helpful and informative, and as you start making decisions to build "real
world" Silverlight applications this information will give you the
confidence you need to effectively evaluate the new platform. Silverlight still
has a ways to go to be on par with mature platforms like WinForms and ASP.NET,
but clearly it is making-up ground quickly.
A
complete set of UI components is essential to making any development platform a
productive environment, and beta 1 finally moves Silverlight closer to
"development ready." Whether or not the current state is enough for
your needs is obviously up to you to determine, but with this article under
your belt, your choice should be a lot clearer.
No comments:
Post a Comment