New Silverlight controls suite delivered by Microsoft #PDC08

.NET, PDC, Silverlight, Technical stuff, Work
See comments

A few minutes ago, Microsoft released a brand new suite of controls for Silverlight. The list is impressive! From now on, you can download these controls, the documentation and samples, and start coding! This post will give you a first insight into these controls based on a preview version of the set. This should make you want to experiment more and to discover more by yourself!

One interesting thing that the team mentioned is that the controls which don’t exist in WPF yet (for example Chart) will also profit from this effort, and the team made its best to code in a way that can be easily ported to WPF later. This kind of Silverlight-to-WPF conversion is relatively new, so it will be interesting to hear the team’s experiences about that when they’re done.

Getting the Silverlight controls

The controls are distributed on Codeplex by the team, at http://codeplex.com/Silverlight. This means that (like other projects before such as the ASP.NET MVC) they will be distributed with an open source license (MS-PL) and members of the community will be welcomed to contribute. As such, they complement other open source projects such as the Silverlight Contrib project at http://www.codeplex.com/silverlightcontrib.

To install the Silverlight controls, download the assemblies from the Codeplex site and save them into a folder on your hard disk.

Integrating the controls in a Silverlight application

Because the controls are not part of the standard Silverlight distribution (yet?), you need to reference the assemblies containing them from the Silverlight application. This is very simple: In the Silverlight application, in the Solution Explorer in Studio 2008, right click on the Silverlight project. Select Add Reference from the context menu and use the Browse tab to select the assembly/assemblies you want to reference. There are 3 assemblies:

  • Microsoft.Windows.Controls.DataVisualization.dll: Contains the Chart control and associated classes.
  • Microsoft.Windows.Controls.Theming.dll: Contains the ImplicitStyleManager and associated classes.
  • Microsoft.Windows.Controls.dll: Contains all other controls.

As usual when you want to use external assemblies in Silverlight, you need to add a namespace to your XAML file. Visual Studio 2008 assists you in this task. For example:

<UserControl
   x:Class="MyApplication.MyControl"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">
   

Chart

I want to start with one of the most impressive control of the suite: the Chart control. That’s right, Silverlight comes now with a Chart delivered by Microsoft. After the acquisition of some technology (and resources aka people) from Dundas, Microsoft started developing charting components for WinForms and ASP.NET. based on that experience, we now get a chart control in Silverlight too.

The Chart control comes with a dedicated Sample application in which many variations are shown. The control supports Column charts, Pie charts, Line charts and Scatter charts (this last one displays all the points without a line connecting them). To enhance the data visualization, the control allows defining axis labels, axis range, legends, titles. It is also interactive and parts of the chart (for example a slice of a Pie chart) react to mouse events such as mouseover or selection. Finally, it reacts dynamically (and with animations) to changes in the underlying collection, providing a real time view of data. There are a few cool demos of this in the Samples collection, be sure to check it out! All in all, it is a very impressive control, especially for a V1.

Columns chart
Pie chart
Another Pie chart
Line chart
Scatter chart

TreeView

The Treeview is quite a well known control, and was sorely missing in Silverlight. I think I even saw some 3rd party implementations for this component. Well, now it is available as part of the controls suite.

The control can be “filled” with data either explicitly by adding TreeViewItems to it, or data bound to a hierarchical collection of elements. If an element in the collection is also a collection, then a new level will be added to the Treeview. This last scenario is of course more interesting, since it allows dynamically filling your TreeView with data, from example from an collection obtained from an external file, or from a web service call.

I didn’t have much time to play with this complex control, but what I saw in the Sample code so far seems to follow the same principles as in WPF, for example using the TreeView’s ItemContainerGenerator property to get a given TreeViewItem. For more info about this, you should really check Dr WPF‘s fabulous series about ItemsControls in WPF.

In the picture below, note how the Treeview’s ItemTemplate is used to modify the way the item is displayed. As usual with Silverlight controls, the TreeView and its items can be templated to look pretty much like anything you want.

Data displayed in TreeView (extract)
Data displayed in TreeView (extract)
 
TreeView

DockPanel

For people coming from the WPF world, DockPanel is pretty clear. In fact, it will remind people coming from the Java world of the model we were using to build user interfaces before the Swing UI framework appeared. Any child of the DockPanel can be arranged on the Top, Left, Right or Bottom of the DockPanel, using corresponding attached properties. The figure below shows a “spiral DockPanel” where every child is placed successively at the Left, Top, Right and Bottom, and also shows how the elements are arranged.

WrapPanel

Another well-known panel in WPF made it to Silverlight. WrapPanel is really nice to display data on a surface of which the size might change dynamically. The panel will “wrap” the elements dynamically. For example, the last element of the first line will automatically become the first element of the second line when the width of the panel is reduced.

In WPF, we now have 3rd party panels adding some dynamism to the wrapping action (for example from the famous Kevin Moore‘s bag’o’tricks so it will be interesting to see the same effects applied to Silverlight.

WrapPanel (narrow)
WrapPanel (wider)

ViewBox

ViewBox also comes from WPF. It is a very handy container which will automatically scale its content to fit its width and height. Since Silverlight UI elements are vector based, this provides a very seamless zoom functionality. It also allows an application to be automatically scaled to the size of the window in which it is displayed. Some time ago, I had written a blog article showing how to do this in Silverlight 1.1 with a ScaleTransform, but using a ViewBox is much more elegant and easy! Simply wrap your main panel (the LayoutRoot) into a ViewBox et voilà.

Small window
Small window
 
Bigger window without Viewbox
Bigger window without Viewbox
 
Bigger window with Viewbox
Bigger window with Viewbox
 

Expander

An Expander is handy when you want to hide/display element to save space. This control is quite straightforward.

On a side note, the Expander’s content can be designed in Blend by setting the “IsExpanded” property to True temporarily.

Expander (collapsed)
Expander (expanded)
 

NumericUpDown and UpDownBase

This is another very simple control that was missing before. It provides a way to guide the user in entering numeric values. The control is easy to customize with properties. For example, you can specify if the user can edit the value manually or not, how many decimals should be displayed, maximum, minimum value and step.

Interestingly, the NumericUpDown derives from the UpDownBase class. Yes it’s a generic class! This class can be used to specify other type of UpDown controls, for example acting on a DateTime, etc… By overriding the methods OnIncrement, OnDecrement, ParseValue and FormatValue, you easily implement how any type of value must be handled by the UpDown control.

AutoCompleteBox

This control is a TextBox which proposes a choice to the user entering text. The choices are coming from an ItemsSource or even from a connected data provider. Alternatively, the developer can also provide unbound data “on the fly” by subscribing to an event which will be called when text is entered in the box. You can then dynamically assign a new collection of items to the AutoCompleteBox’ ItemsSource. The way that the items are searched can be configured with properties:

  • IsTextSearchEnabled>: If set to True, the first item in the suggestion list will be entered in the TextBox immediately as the user is typing. Of course, as the user refines the search, another item might be selected (see figures below).
  • SearchMode: This property can be set to multiple values: StartsWith (and StartsWithCaseSensitive) mean that the items will only be displayed if they start with the entered string. Contains (and ContainsCaseSensitive) displays the items if they contain the entered string. Equals (and EqualsCaseSensitive) displays the items only if there is an exact match.
Basic AutoCompleteBox
Basic AutoCompleteBox
 
AutoCompleteBox with IsTextSearchEnabled = True
AutoCompleteBox with IsTextSearchEnabled = True
 
AutoCompleteBox with SearchMode = Contains
AutoCompleteBox with IsTextSearchEnabled = True

Finally, Custom displays the items according to a custom filter (for example by setting the “ItemFilter” property to a Lambda expression). For example, in the sample displayed below, the airport Los Angeles is displayed becasue the FAA code (LAX) contains the string “la”. The airport “Fort Lauderdale” is displayed because its name contains this same string.

DepartureAirport.ItemFilter = (search, item) =>
{
    Airport airport = item as Airport;
    if (airport != null)
    {
        // Interested in: Name, City, FAA code
        string filter = search.ToUpper(CultureInfo.InvariantCulture);
        return (airport.CodeFaa.ToUpper(CultureInfo.InvariantCulture).Contains(filter)
            || airport.City.ToUpper(CultureInfo.InvariantCulture).Contains(filter)
            || airport.Name.ToUpper(CultureInfo.InvariantCulture).Contains(filter));
    }

    return false;
};
Setting the ItemFilter to a lambda expression
 
AutoCompleteBox with lambda expression filter
AutoCompleteBox with lambda expression filter
 

Label

This Label control is pretty much the same one than the one in WPF. It can be used to display any type of content (text, image, any XAML elements). It can also be formatted like a TextBlock

Using and formatting a label
Theming

In addition to all the goodies proposed here, the team came with a solution to facilitate managing styles and creating themes in Silverlight. You can now use attached properties defined in a class called ImplicitStyleManager. What it does is pretty clever: If you have an element containing other elements (for example a Panel or a Border), the styles you define in the container’s resources will automatically be applied to all the children (and to the children’s children). Alternatively, you can even specify an external resource dictionary from which the styles will be applied.

What this element reaches is that the implicit style behavior available in WPF (where you can specify that all the buttons of an application must use a certain style by default) is not also available in Silverlight. And since these styles can even be defined in an external resource dictionary (something that was also not available until now in Silverlight), you have the same kind of flexibility than in the big sister WPF.

The control also allows you to start with unstyled controls and apply the styles at a later point, programatically. You can also specify set the attached property “ImplicitStyleManager.ApplyMode” to “Auto” to specify that the implicit styles should be applied to any new elements added to the tree during runtime (for example ListBoxItems, etc…). If you set this property to “OneTime”, the styles will not be automatically applied to new elements (on the other hand, I suppose that setting this property to Auto will have an impact on performances).

Note however that this control still doesn’t allow switching styles during runtime, due to limitations of the core Silverlight. If you want to apply a different style to a running Silverlight application, you still need to reload the web page containing the application, effectively reloading the whole application (and losing the state, unless you take measures to prevent this explicitly). ImplicitStyleManager is a step in the right direction, but there is still some work that needs to be done on themes and styles to get the same level of dynamism that WPF developers know and love.

<StackPanel>
   <StackPanel.Resources>
     <Style TargetType="Button">
       <Setter Property="Foreground" Value="Green" />
     </Style>

     <Style TargetType="TextBlock">
       <Setter Property="Foreground" Value="Green" />
     </Style>
   </StackPanel.Resources>

   <StackPanel x:Name="dynamicContainer">
     <Button Content="Button inside border" />
     <TextBlock>TextBlock inside border</TextBlock>
   </StackPanel>
</StackPanel> 
Implicit styles in WPF
 
<StackPanel theming:ImplicitStyleManager.ApplyMode="Auto">
   <StackPanel.Resources>
     <Style TargetType="Button">
       <Setter Property="Foreground" Value="Green" />
     </Style>

     <Style TargetType="TextBlock">
       <Setter Property="Foreground" Value="Green" />
     </Style>
   </StackPanel.Resources>

   <StackPanel x:Name="dynamicContainer">
     <Button Content="Button inside border" /> 
     <TextBlock>TextBlock inside border</TextBlock>
   </StackPanel>
</StackPanel> 
Implicit styles in Silverlight
 

Samples

Note that the controls are distributed with samples (and their associated source code) which should allow you to get started very easily.

I hope that this post gave you an interest to look deeper into this interesting new set of controls. And don’t forget, this is open source, so if you want to contribute, you can do so on Codeplex!

Previous entry | Next blog entry

Comments for New Silverlight controls suite delivered by Microsoft #PDC08