Posted on Monday July 26, 2010

Silverlight snippets

This is a collection of simple/beginner level Silverlight snippets that will slowly build up over time. A lot of the answers here come thanks to the Silverlight tag on Stackoverflow and the Microsoft silverlight forums.

Stretched line

Where you don’t know a line’s width, you can use the stretch property to make it fit its parent.

<Line Stroke="#FF6565C1" StrokeDashArray="1 1" StrokeThickness="1" X1="0" Y1="0" X2="0" Y2="0" Stretch="Fill"/>

n.b. Fill doesn’t work with lines.

Dashed Line

For dashed lines you can’t use the stretch trick above, so you’re limited to specifying the width:

<Line Stroke="#FF6565C1" StrokeDashArray="1 1" StrokeThickness="1" X1="0" Y1="0" X2="100" Y2="0"/>

You can also achieve this with a Rectangle:

<Rectangle Stroke="#FF6565C1" StrokeDashArray="1 1" StrokeThickness="1" Height="1"/>

Setting the Fill property will fill the rectangle rather than give you a dashed line. One problem with using a Rectangle however is you get quite an ugly thick dashed line, as it has essentially draw 2 lines:

Silverlight dashed rectangle

Updating an attached property in code

An attached property is one that references a parent control’s property in XAML, for example the Canvas.Left and Canvas.Top properties below:

<Canvas>
<TextBox Name="MyTextbox" Canvas.Left="100" Canvas.Top="100" Height="200" Width="1000"/>
</Canvas>

You can set these properties in C# like so:

Canvas.SetTop(MyTextbox,100d);
// Alternative weak-typed method
MyTextbox.SetValue(Canvas.TopProperty, 100d);

Bind a ControlTemplate’s control in the codebehind

This is done by overriding the ApplyTemplate method, and can’t be done in the constructor as the tree doesn’t exist at that point. You also need to use GetTemplateChild:

public class TemplatedControl1 : ContentControl
{
    private Button _button;
    public TemplatedControl1()
    {
        this.DefaultStyleKey = typeof(TemplatedControl1);
    }
    
    public override void OnApplyTemplate()
    {
        _button = (Button)GetTemplateChild("MyButton");
        _button.Click += new RoutedEventHandler(button_Click);
    }
    
    private void button_Click(object sender, RoutedEventArgs e)
    {
    }
}

Setting Image.Source in the codebehind

As the Image.Source property has its own converter in XAML, you can use a plain string. Inside C# it’s a more long-winded:

Image image = (Image)GetTemplateChild("MyImage"); // or use FindName()
image.Source = new BitmapImage(new Uri("/MyNamespace;component/dolphin.png",UriKind.Relative));

Setting a TextBox to readonly without a grey background

In Silverlight 4 there is no control that allows you select text from a label, as you would on a HTML page. To get around this shortcoming you need to use a TextBox, set its IsReadOnly property to true. And then to get around the grey background issue, use the following style. This style ignores validation.

If you want underlined text or decorations you need to stick to the TextBlock control.

<Style x:Key="ReadOnlyStyle" TargetType="TextBox">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Background" Value="#FFFFFFFF"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="MouseOver"/>
<vsm:VisualState x:Name="Disabled" />
<vsm:VisualState x:Name="ReadOnly"/>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Unfocused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
<SplineDoubleKeyFrame KeyTime="0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Border x:Name="Border" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
<Grid>
<Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
</Border>
</Grid>
</Border>
<Border x:Name="DisabledVisualElement" IsHitTestVisible="False" Opacity="0" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}"/>
<Border x:Name="FocusVisualElement" Margin="1" IsHitTestVisible="False" Opacity="0" BorderBrush="#FF6DBDD1" BorderThickness="{TemplateBinding BorderThickness}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Creating an animation in C

Duration duration = new Duration(TimeSpan.FromMilliseconds(500));
DoubleAnimation animation = new DoubleAnimation();
animation.To = 100;
animation.Duration = duration;
//animation.EasingFunction = new QuadraticEase();
Storyboard storyBoard = new Storyboard();
storyBoard.Duration = duration;
storyBoard.Children.Add(animation);
Storyboard.SetTargetName(animation, "MyTextBox");
Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));
canvas1.Resources.Add("mysb", storyBoard);
storyBoard.Begin();

FlowDocuments and formatted text

Silverlight 4 doesn’t support the FlowDocumentReader tag however you can get formatted text into a TextBlock and the new RichTextBox control using the same, slimmed down WPF syntax. I haven’t been able to find a comprehensive list of supported tags, instead I’ve just used trial and error. The snippet below is based on the Regex tester from the tools section. There’s a lot more information on MSDN.

string formatted = "<Run FontWeight='Bold' Foreground='Green'>Some green bold text</Run>";
string xaml = "<UserControl " +
"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  " +
"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  " +
"xmlns:d="http://schemas.microsoft.com/expression/blend/2008" " +
"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" " +
"xmlns:toolkit="clr-amespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"  " +
"xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input">";
xaml += "<ScrollViewer Height='130'><TextBlock TextWrapping='Wrap' Width='300'>" + formatted + "</TextBlock></ScrollViewer></UserControl>";

// Add to a ContenControl
_contentControlOutput.Content = XamlReader.Load(xaml);

Adding linebreaks to a TextBlock (or RichTextBlock)

When you paste into either of these controls, newlines come up as r. To make these visible you need to use a control like so:

txt = txt.Replace("\r", "<LineBreak/>");

Setting initParams and retrieving them

The initParams parameter for the tag in your silverlight HTML host allows you to pass values into the silverlight control, in a querystring format.

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" Height="100%">
<param name="source" value="my.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="4.0.50401.0" />
<param name="autoUpgrade" value="true" />
<param name="initParams" value="name=bob&age=30&height=180" />
</object>

To retrieve them:

Uploading a file in Silverlight

This is a very basic example of uploading a file.

Trapping keyboard modifiers (CTRL,SHIFT, ALT) keys in Silverlight textboxes

This isn’t immediately obvious in the KeyDown and KeyUp events for a textbox, if you come from winforms. If you’re looking for one of the keyboard modifiers it’s found in the KeyBoard class as a static member:

void TextBoxKeyDown(object sender, KeyEventArgs e)
{
	if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.V)
		// Do something
}

Accessing the querystring in Silverlight

if (HtmlPage.Document.QueryString.ContainsKey("MyKey"))
string val = HtmlPage.Document.QueryString["MyKey"];

The HyperLinkButton by default draws a big blue box around itself when you press it. This is a usability cue for keyboard users but doesn’t match the hyperlink you’ve grown to love in HTML. The big blob of XAML fixes this, simply style your hyperlink button: