Handling Dynamic Storyboards and Animations in Silverlight 2

Posted on December 17, 2008 by dwahlin.
Categories: ASP.NET, Contributors, Silverlight.

Animations are a key part of Silverlight 2 that allow your applications to stand out from all of the boring and dull applications floating around on the Web.  In previous articles I’ve written about storyboards and animations but as a quick review, Silverlight relies upon a Storyboard element to define several different types of animations such as DoubleAnimation (which animates object properties of type double) and ColorAnimation (which animates color properties).  In this article I’ll show you how Silverlight can be used to create animations programmatically and how you can interact with animations defined declaratively in a XAML file using C#.

For this example I’ll create a simple “lightbox” style container that can display pictures from Flickr.  As the picture is being shown the box will grow from a height/width of 0 to a larger size that’s determined by the size of the browser.  Three different animations will be performed by the image display container:

  • Animate the Width from 0 to the width of the browser / 1.5
  • Animate the Height from 0 to the height of the browser / 1.5
  • Animate the Opacity from 0 to 1

If you know the To and From values of the animations upfront then it’s easiest to define them in the XAML file.  In cases where there’s an unknown animation property value, you can create the storyboard and animation objects programmatically or update properties of an existing Storyboard defined in XAML.  In this case a Border control will be animated:

<Border x:Name="LightBoxControl" BorderBrush="Black" BorderThickness="3" 
        CornerRadius="10"  
        Height="20" Width="20" Opacity="0" Margin="5" 
        MouseLeftButtonDown="Image_MouseLeftButtonDown">
    <Border.Background>
        <LinearGradientBrush EndPoint="0.893,0.116" StartPoint="0.403,0.694">
            <GradientStop Color="#FFB9B9B9" Offset="1"/>
            <GradientStop Color="#FF4F4F4F" Offset="0"/>
            <GradientStop Color="#FF666666" Offset="0.496"/>
        </LinearGradientBrush>
    </Border.Background>
    <StackPanel x:Name="spImage">
        <Border HorizontalAlignment="Right" VerticalAlignment="Top" BorderBrush="Black" 
                BorderThickness="1" CornerRadius="8" Background="LightGray" Width="60" Height="25">
            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="12" 
                       Text="Close" />
        </Border>
        <Rectangle x:Name="LightBoxImage" HorizontalAlignment="Center" 
                   Fill="Black" RadiusX="10" RadiusY="10" 
                   Stroke="LightGray" StrokeThickness="2" Margin="5">
        </Rectangle>
    </StackPanel>
</Border>

Here’s an example of programmatically creating a Storyboard and defining the 3 animations mentioned earlier to change the Width, Height and Opacity properties of the Border control:

double? width = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty("offsetWidth") / 1.5;
double? height = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty("offsetHeight") / 1.5;
//Programmatic way to create a storyboard and animations
Storyboard sb = new Storyboard();

//Create animation for Border control's Width
DoubleAnimation wa = new DoubleAnimation();
wa.Duration = new Duration(TimeSpan.FromSeconds(0.5))
wa.From = 0;
wa.To = width;
Storyboard.SetTarget(wa, LightBoxControl);
Storyboard.SetTargetProperty(wa, new PropertyPath(Border.WidthProperty));
sb.Children.Add(wa);

//Create animation for Border control's Height
DoubleAnimation ha = new DoubleAnimation();
ha.Duration = new Duration(TimeSpan.FromSeconds(0.5));
ha.From = 0;
ha.To = height;
Storyboard.SetTarget(ha, LightBoxControl);
Storyboard.SetTargetProperty(ha, new PropertyPath(Border.HeightProperty));
sb.Children.Add(ha);

//Create animation for Border control's Opacity
DoubleAnimation oa = new DoubleAnimation();
oa.Duration = new Duration(TimeSpan.FromSeconds(0.5));
oa.From = 0;
oa.To = 1;
Storyboard.SetTarget(oa, LightBoxControl);
Storyboard.SetTargetProperty(oa, new PropertyPath(Border.OpacityProperty));
sb.Children.Add(oa);

this.spImage.Width = width.Value - 30;
this.spImage.Height = height.Value - 30;
this.LightBoxImage.Width = width.Value - 75;
this.LightBoxImage.Height = height.Value - 75;
sb.Begin();

In this example the final height and width of the target Border control are determined by grabbing the offsetWidth and offsetHeight values using the HtmlPage class.  Once those values are determined a Storyboard object is created along with the three animations all of type DoubleAnimation.  Each animation takes 1/2 second to complete and animates the Border control’s Height, Width and Opacity properties respectively. 

Looking through the code for each animation object you’ll notice that it is associated with the target object and target object property using the Storyboard.SetTarget() and Storyboard.SetTargetProperty() static methods respectively.  This may seem strange at first glance but makes sense once you understand the concept of attached properties.  Each animation object is added to the parent Storyboard object using the Children.Add() method and the Storyboard is started by calling the Begin() method.

Interacting with Storyboards and Animations Defined in XAML

The programmatic approach to creating animations works great when there’s a lot of dynamic data being fed into animation objects.  However, in this example only the Height and Width properties are being changed on the Border control.  That’s a lot of code to write to change two properties.  Rather than defining everything programmatically you can instead define the storyboard and associated animations declaratively and fill in the dynamic pieces at runtime.  Here’s an example of defining the 3 animations shown earlier in XAML:

<Storyboard x:Name="sbShow">
    <DoubleAnimation x:Name="daWidth" Storyboard.TargetName="LightBoxControl"
                     Storyboard.TargetProperty="Width"
                     From="0" Duration="00:00:0.5" />
    <DoubleAnimation x:Name="daHeight" Storyboard.TargetName="LightBoxControl"
                     Storyboard.TargetProperty="Height"
                     From="0" Duration="00:00:0.5" />
    <DoubleAnimation Storyboard.TargetName="LightBoxControl"
                     Storyboard.TargetProperty="Opacity"
                     From="0" To="1" Duration="00:00:0.5" />
</Storyboard>

Before the storyboard starts to play the To property of the daWidth and daHeight objects can then be assigned values as shown next:

double? width = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty("offsetWidth") / 1.5;
double? height = (double?)System.Windows.Browser.HtmlPage.Document.Body.GetProperty("offsetHeight") / 1.5;


//Define how big the Border control should be animated to by setting the To property value

this
.daWidth.To = width; this.daHeight.To = height;
this.spImage.Width = width.Value - 30; this.spImage.Height = height.Value - 30; this.LightBoxImage.Width = width.Value - 75; this.LightBoxImage.Height = height.Value - 75;
this.sbShow.Begin();

And that’s all there is to it!  Silverlight makes it easy to work with dynamic animations whether programmatically or through modifying storyboards defined in XAML.  Download a working version of the Flickr lightbox application here if you’d like to see the animations in action (as well as some others).

 image 
Interested in learning more about Silverlight 2 application development?  Visit Interface Technical Training’s website for more information about their Silverlight 2 training course or call 1-800-264-9029.  I'll be teaching the course in the Phoenix area (or onsite at customer locations).

Using Styles to Define Silverlight 2 Control Templates

Posted on November 2, 2008 by dwahlin.
Categories: Contributors, Silverlight.

Silverlight 2 allows styles to be defined to prevent duplication of attributes across controls in a XAML file. In a previous post I demonstrated how styles could be defined and used. As a review, here's an example of defining a style named ButtonStyle that targets a Button control:

<Style x:Key="ButtonStyle" TargetType="Button">
    <Setter Property="FontFamily" Value="Arial" />
    <Setter Property="FontWeight" Value="Bold" />
    <Setter Property="Width" Value="100" />
    <Setter Property="Height" Value="25" />
    <Setter Property="Margin" Value="5,10,0,10" />
</Style>

The style can be applied to one or more buttons using the following StaticResource syntax:

<Button x:Name="btnSubmit" Style="{StaticResource ButtonStyle}" />
<Button x:Name="btnCancel" Style="{StaticResource ButtonStyle}" />

In addition to defining control property values, styles can also be used to define control templates. This is useful any time you'd like to customize a control and make it look and feel different than it looks out of the box. In this post you'll see how a standard rectangular Button control can be made into a rounded button. Here’s an example of what the standard Silverlight 2 Button control looks like:

image

By using control templates you can do virtually anything you'd like to a control. Here’s an example of a Button that has a custom style and control template defined to give it a flat look with rounded corners:

image

Control templates can be defined within a control's Resources section, within a UserControl's Resources section, or within the Application.Resources section of App.xaml. Defining a template in App.xaml is recommended anytime you'd like to re-use a template across multiple controls in an application.  Here's an example of a style named ButtonFlatStyle that defines a custom control template for a Button:

<Style x:Key="ButtonFlatStyle" TargetType="Button">
    <Setter Property="Width" Value="100" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">                        
                <Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"
                        Background="{TemplateBinding Background}" 
                        CornerRadius="8" BorderBrush="Black" BorderThickness="1">
                     <ContentPresenter Content="{TemplateBinding Content}" 
HorizontalAlignment
="Center" VerticalAlignment="Center"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>

Looking through the ButtonFlatStyle style you'll see that it first defines a width of 100. It then defines a Template property with an associated value. Although this is a very simple example of a control template, you can see that a template is nothing more than a way to define custom control rendering. More complex templates may use many more controls, styles, bindings and even include animations using Silverlight's Visual State Manager (a topic that I'll save for a later article).

Control templates are defined using the ControlTemplate element which acts as a container for template controls and defines the target control type of the template by using the TargetType attribute. This example targets a Button control. The ControlTemplate element shown here includes a Border child element which is used to generate rounded corners using the CornerRadius property.

Notice that a special TemplateBinding syntax appears within several of the Border element's attribute values. What's a TemplateBinding and why would you use it? It's nothing more than a way to allow control properties defined by a developer to be used in the control template. In other words, if a developer defines a Button control that uses the ButtonFlatStyle style, any Width, Height or Background values that they set on the control will automatically be used within the template. This allows the control template to take developer customizations into account.

Within the Border control you'll see a ContentPresenter XAML element. This element marks where the control's content (such as a Button's Content attribute value) will be placed within the template. It literally handles "presenting" the content within the template. The Content="{TemplateBinding Content}" attribute binds the target control's Content property to the ContentPresenter's Content property. To clarify this more, consider the following XAML code:

<Button x:Name="btnClear" Content="Clear" 
  Background="LightGray" Style="{StaticResource ButtonFlatStyle}" />

The ContentPresenter element defined within the template will render the text "Clear" within the control template's Border element. If a control's Content property defines more complex content it would also be applied using the ContentPresenter. Here's an example of defining complex content within a Button control:

<Button x:Name="btnClear2" Click="btnSubmit_Click" Background="LightGray"
  Style="{StaticResource ButtonFlatStyle}">
    <Button.Content>
        <StackPanel Orientation="Horizontal">
            <Image Source="/red_x_mark.jpg" Width="20" Height="19" 
             VerticalAlignment="Center" />
            <TextBlock Margin="5" Text="Clear" Foreground="Navy" 
             VerticalAlignment="Center" />
        </StackPanel>
    </Button.Content>
</Button>

In this example the content consists of additional controls rather than only basic text. Here’s an example of how the custom content would be rendered by the control template:

image

Control templates allow you to take over the look and feel of a control and customize how it's rendered in a Silverlight 2 application. By defining control templates within styles you can easily re-use a template across multiple controls.

Silverlight Toolkit Overview and Samples

Posted on October 28, 2008 by dwahlin.
Categories: Contributors, Silverlight.

Controls are where it’s at these days in the programming world. By using them you maximize re-use, enhance productivity and avoid building custom functionality. Plus, when you need a control to do something different you can always extend it rather than writing everything from scratch.

If you’ve used ASP.NET AJAX then you’ve likely used controls from toolkits such as the ASP.NET AJAX Control Toolkit in your applications. Microsoft has also released a Silverlight Toolkit with new controls and functionality that can be used in Silverlight 2 applications. The controls are grouped into “quality bands” with the existing controls currently fitting into either the “Preview” or “Stable” bands. Additional information about quality bands and the toolkit controls can be found on Shawn Burke’s blog.

Controls included in the Silverlight Toolkit include:

  • AutoCompleteBox
  • ButtonSpinner
  • Chart
  • DockPanel
  • Expander
  • HeaderedItemControl
  • HeaderedContentControl
  • ImplicitStyleManager
  • Label
  • NumericUpDown
  • TreeView
  • ViewBox
  • WrapPanel

The new controls live in the Microsoft.Windows.Controls.dll assembly which contains several namespaces such as Microsoft.Windows.Controls (where most of the controls live) and Microsoft.Windows.Controls.DataVisualization.Charting (where the charting control and related classes live). To get started using them you’ll need to reference the Microsoft.Windows.Controls assembly provided in the toolkit and then add the controls to your Visual Studio 2008 Toolbox by right-clicking on it and selecting “Choose Items”. Select the Silverlight Components tab, browse to the assembly and then check the checkbox next to the controls you’d like to add and then drag them into a Silverlight 2 XAML file. This will add the proper namespace onto the UserControl root element as shown next:


    

In this post I’ll discuss a few of the new controls that I personally find quite useful and show what they’re are capable of doing. Future posts will drill into different controls and demonstrate additional details about how they can be used.

Managing Silverlight Styles with ImplicitStyleManager

In a previous post I wrote about how styles can be defined and assigned to controls. While the default technique of defining and applying styles works, it certainly can be a pain to add Style=”{StaticResource YourStyleKey}” to all of the controls needing to pick-up a specific style in an application. WPF provides a way to “implicitly” apply styles to controls but this functionality isn’t available in Silverlight 2 unfortunately. Enter the ImplicitStyleManager provided by the Silverlight Toolkit. By using ImplicitStyleManager styles that target a specific control type can be applied without manually adding a Style attribute to each control. The class lives in the Microsoft.Windows.Controls.Theming namespace (Microsoft.Windows.Controls assembly) which needs to be referenced in the XAML file as shown next:

xmlns:theming="clr-namespace:Microsoft.Windows.Controls.Theming;assembly=Microsoft.Windows.Controls.Theming"
>

Here’s an example of using ImplicitStyleManager within a control that has styles defined locally within its Resources section:


    
        
            
            
        
        
            

This example applies the styles to the appropriate controls (a Button and a TextBox in this case) automatically. The theming:ImplicitStyleManager.ApplyMode attribute makes this possible. Looking at the control definitions in the StackPanel you’ll see that no Style attribute is added. Instead, the styles are “implicitly” applied based on the Style element’s TargetType. You may also note that no x:Key is defined on the Style elements since it’s not needed.

ImplicitStyleManager can also be used to apply styles defined in a theme file (a XAML file containing a ResourceDictionary section) as shown next:


    
        

A portion of the CustomTheme.xaml file referenced by the code above is shown next:


   
    


Adding Style to Silverlight 2 Controls

Posted on October 23, 2008 by dwahlin.
Categories: ASP.NET, Contributors, Silverlight.

Silverlight 2 provides a nice set of controls that can be used to capture and display data. While control properties can be set directly on the control in a XAML file using attributes, some properties will be duplicated between controls causing maintenance headaches. The following example demonstrates this problem:

<Button x:Name="btnSubmit" FontFamily="Arial"
FontWeight="Bold" Width="100" Height="25" Margin="10" />

<Button x:Name="btnCancel" FontFamily="Arial"
FontWeight="Bold" Width="100" Height="25" 
Margin="10" />

Notice that both Button controls define the same values for FontFamily, FontWeight, Width, Height and Margin properties. Although this XAML works fine, you’ll want to encapsulate repeated properties into re-useable styles so that you can apply them to any Button quickly and easily. It’s really the same concept used in Web pages. Developers create CSS stylesheets to encapsulate styles into re-useable classes that can be applied to various elements. The same overall process can be used in Silverlight 2 applications.

Silverlight 2 allows styles to be defined in several resource sections including within a control, within a UserControl or within App.xaml’s application resources section. While styles can be defined in the UserControl.Resources section of a Page.xaml file, re-useable styles that may be used across multiple XAML files should be placed in the App.xaml file within the Application.Resources section. Silverlight 2 projects add an App.xaml file that contains the following default XAML code:

<Application 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
  x:Class="UsingStylesAndTemplates.App">
    <Application.Resources>

        <!-- Styles go here -->

    </Application.Resources>
</Application>

Control styles can be placed in the Application.Resources element. Styles are defined by using the Style element as shown next. The Style element defines the style’s key as well as the type of control that it targets:

<Style x:Key="ButtonStyle" TargetType="Button">

</Style>

This example defines a style that has a key of ButtonStyle. The style can only be applied to Button controls. 

Styles are defined by using a Setter element which contains Property and Value attributes. An example of converting all of the repeated attributes shown earlier on the Button controls into a re-useable style is shown next:

<Style x:Key="ButtonStyle" TargetType="Button"> 
    <Setter Property="FontFamily" Value="Arial" /> 
    <Setter Property="FontWeight" Value="Bold" /> 
    <Setter Property="Width" Value="100" /> 
    <Setter Property="Height" Value="25" /> 
    <Setter Property="Margin" Value="5,10,0,10" /> 
</Style>

In addition to defining styles within App.xaml you can also define them within a UserControl.Resources section in cases where the style is only used within the scope of the UserControl:

<UserControl.Resources> 
    <Style x:Key="ButtonStyle" TargetType="Button"> 
        <Setter Property="FontFamily" Value="Arial" /> 
        <Setter Property="FontWeight" Value="Bold" /> 
        <Setter Property="Width" Value="100" /> 
        <Setter Property="Height" Value="25" /> 
        <Setter Property="Margin" Value="5,10,0,10" /> 
    </Style> 
</UserControl.Resources>

Once a style has been defined, it can be applied to a control by using the Style attribute. Because styles are statically defined within a resources section they can be referenced using the StaticResource keyword. An example of applying the ButtonStyle shown earlier to two buttons is shown next:

<Button x:Name="btnSubmit" Style="{StaticResource ButtonStyle}" /> 
<Button x:Name="btnCancel" Style="{StaticResource ButtonStyle}" />

This is equivalent to assigning a CSS class to an HTML element's style attribute and allows the two buttons to pick up the ButtonStyle style without having to define the same properties over and over.  In a future post I'll discuss another interesting aspect of Silverlight 2 styles referred to as control templates and show how they can be used to completely customize the look and feel of a control.

What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

Posted on August 20, 2008 by dwahlin.
Categories: C#, Contributors.

I’ve written a few posts about LINQ to SQL and am generally a big fan of the technology (even with its weaknesses) since it’s very productive.  After creating a custom DataContext object using the LINQ to SQL designer (or one created by hand) I always ensure that the object is wrapped in a “using” statement so that the Dispose() method is called:

using (MyDataContext context = new MyDataContext())
{

//Perform query }

I had assumed that not properly disposing of the DataContext object would lead to orphan SQL connections which is of course bad and will likely lead to your DBA holding a grudge against you for life. :-)

Steven Walther recently posted on the subject of disposing of DataContext objects and provided some interesting insight into what actually happens.  From what he says it sounds like the DataContext object acts much like the SqlDataAdapter class.  It opens the connection right before a query is executed and closes it immediately after.  I don’t want to steal Steven’s thunder so check out his post on the subject (the last part of the article talks about the consequences…or lack of consequences…of not calling Dispose()). 

I haven’t had time to verify the details in Reflector yet, but given that Steven’s one of the more intelligent people I know I’m confident that the details he presents are accurate.  It still feels more correct to wrap “using” statements around any object that implements IDisposable or explicitly call Dispose() in my opinion, but it’s good to know how the DataContext object works behind the scenes.