Page view counter

October 2008 - Posts

Silverlight Toolkit: DockPanel

Hi Folks,

I’d like for us to talk about one of the new controls in the Silverlight Toolkit – DockPanel.

In the following article we’ll deep dive into DockPanel and see how it behaves in different situations.

 

 

Setup

1. Create a new project.

File --> New --> Project

Select project type

2. Add a reference to the Silverlight Controls assembly (Microsoft.Windows.Controls.dll) which can be downloaded at http://codeplex.com/Silverlight.

image    image

3. Add a Silverlight Toolkit controls xmlns reference to the XAML page.

image

4. Add a DockPanel to the Page with LastChildFill=False. (we’ll talk about this property later in this article)

<controls:DockPanel LastChildFill="False" />

Here’s the XAML we just wrote:

<UserControl x:Class="SilverlightControlsNovember2008.Page"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="400" Height="300"

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

    <Border x:Name="LayoutRoot" Background="White" BorderBrush="Black" BorderThickness="1">

        <controls:DockPanel LastChildFill="False" />

    </Border>

</UserControl>

(for the purposes of this specific demo, we changed LayoutRoot to be a <Border> and not a <Grid>. That is so we could see the edge of our visual area)

 

 

Docking a single Item

Let’s add a <Button> to the top our DockPanel.

 

<controls:DockPanel LastChildFill="False">

    <Button Content="#1" />

</controls:DockPanel>

 

And here’s a preview through Visual Studio XAML designer:

image

<Button> Fills all the available space given to the control inside our DockPanel.
So actually Button is perfect for us to learn about DockPanel, since it lets us see exactly where the control is and what the available size for it is.

As we can, the <Button> is Docked to the Left of our DockPanel.

Let’s specify a Controls:DockPanel.Dock Attached property value that would allow us to dock items to areas of the DockPanel.

Dock Enum values

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Top" Content="#1" />

</controls:DockPanel>

image

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Right" Content="#1" />

</controls:DockPanel>

image

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Bottom" Content="#1" />

</controls:DockPanel>

image

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Left" Content="#1" />

</controls:DockPanel>

image

 

 

Docking two items to opposite docking areas

Looking at the previous example it’s pretty easy to figure out what the following XAML would look like.

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Left" Content="#1" />

    <Button controls:DockPanel.Dock="Right" Content="#2" />

</controls:DockPanel>

image

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Top" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

</controls:DockPanel>

image

 

 

Docking the last item to Center

In our first DockPanel example we’ve set some mysterious LastChildFill property to false.

Let’s set LastChildFill=True and put an undocked button as the last child of the DockPanel.

<controls:DockPanel LastChildFill="True">

    <Button controls:DockPanel.Dock="Top" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

    <Button Content="Filler" />

</controls:DockPanel>

image

It’s important to note that Even if we do set DockPanel.Dock property on the last child of a DockPanel, it would still get filled out if LastChildFill=True.

<controls:DockPanel LastChildFill="True">

    <Button controls:DockPanel.Dock="Top" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

    <Button controls:DockPanel.Dock="Left" Content="Filler" />

</controls:DockPanel>

image

You can see the “DockPanel.Dock=Left” is completely ignored and the Last child is still treated as a filler.

 

 

Docking Defaults (LastChildFill=True, Dock=Left)

By default a DockPanel would always treat the last child as a Filler.

<controls:DockPanel>

    <Button controls:DockPanel.Dock="Top" Content="#1" />

    <Button Content="Filler" />

</controls:DockPanel>

image

And by default, any item not Docked to any area, will be docked to the Left.

<controls:DockPanel>

    <Button Content="#1" />

    <Button Content="Filler" />

</controls:DockPanel>

image

Let’s add a few more items so the Default Left docking would be a bit more visible.

<controls:DockPanel>

    <Button Content="#1" />

    <Button Content="#2" />

    <Button Content="#3" />

    <Button Content="Filler" />

</controls:DockPanel>

image

Essentially, DockPanel by default mimics a Horizontal StackPanel besides the fact that it does treat the last item as a filler.

<StackPanel Orientation="Horizontal">

    <Button Content="#1" />

    <Button Content="#2" />

    <Button Content="#3" />

    <Button Content="Filler" />

</StackPanel>

image

 

 

Docking Multiple elements to the same Docking area

You’ve probably noticed in the previous example that the DockPanel stacks items on the same Area.

Let’s have a look at stacking multiple items on all sides.

<controls:DockPanel>

    <Button controls:DockPanel.Dock="Top" Content="#1" />

    <Button controls:DockPanel.Dock="Top" Content="#2" />

    <Button controls:DockPanel.Dock="Top" Content="#3" />

    <Button Content="Filler" />

</controls:DockPanel>

image

<controls:DockPanel>

    <Button controls:DockPanel.Dock="Right" Content="#1" />

    <Button controls:DockPanel.Dock="Right" Content="#2" />

    <Button controls:DockPanel.Dock="Right" Content="#3" />

    <Button Content="Filler" />

</controls:DockPanel>

image

<controls:DockPanel>

    <Button controls:DockPanel.Dock="Bottom" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

    <Button controls:DockPanel.Dock="Bottom" Content="#3" />

    <Button Content="Filler" />

</controls:DockPanel>

image

<controls:DockPanel>

    <Button controls:DockPanel.Dock="Left" Content="#1" />

    <Button controls:DockPanel.Dock="Left" Content="#2" />

    <Button controls:DockPanel.Dock="Left" Content="#3" />

    <Button Content="Filler" />

</controls:DockPanel>

image

The order in which items are stacked is based on the first rule of DockPanel.

image

The First Rule of Fight Club: You Don’t talk about Fight Club

image

The First Rule of DockPanel: The order of DockPanel Children’s determines their placement based on precedence

 

Admittedly it’s not as dramatic as fight club, but it’s still true.

Consider these trivial DockPanel samples:

<controls:DockPanel>

    <Button controls:DockPanel.Dock="Left" Content="#1" />

    <Button controls:DockPanel.Dock="Left" Content="#2" />

    <Button Content="Filler" />

</controls:DockPanel>

<controls:DockPanel>

    <Button controls:DockPanel.Dock="Left" Content="#2" />

    <Button controls:DockPanel.Dock="Left" Content="#1" />

    <Button Content="Filler" />

</controls:DockPanel>

image image

The #1 and #2 Items are placed based on the order of the DockPanel children.

Although that on the surface they’re both docked to the Left exactly, one has precedence over the other.

The order of DockPanel Children’s determines their placement based on precedence.

 

 

Docking Two elements with intersecting Docking areas

We mentioned Precedence, That is also relevant for Intersecting items.

Have a look at these two DockPanels. 

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Top" Content="#1" />

</controls:DockPanel>

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Left" Content="#1" />

</controls:DockPanel>

 image image

Let’s illustrate how this collision would look like: (done with mspaint, not an actual print-screen)

image

Now, it’s obvious that one of these items would need to get the Top-left corner, but which one?
Let’s write some code, run it and we’ll see.

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Top" Content="#1" />

    <Button controls:DockPanel.Dock="Left" Content="#2" />

</controls:DockPanel>

image

And if we change the order of the buttons:

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Left" Content="#2" />

    <Button controls:DockPanel.Dock="Top" Content="#1" />

</controls:DockPanel>

image

So, as we can see – In the first example Button #1 was placed first and it got precedence over Button #2 for the top-left corner.

And in the second example Button #2 was placed first and it got precedence over Button #1 for the top-left corner.

Let’s see this at work with other docking areas.

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Right" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

</controls:DockPanel>

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Bottom" Content="#1" />

    <Button controls:DockPanel.Dock="Right" Content="#2" />

</controls:DockPanel>

image image

So, we can clearly see that the order of items in the DockPanel determines who is docked first to where.

 

 

Docking Multiple elements to intersecting Docking areas

Let’s follow up on the last sample with more than one item per docking area.

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Bottom" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

    <Button controls:DockPanel.Dock="Bottom" Content="#3" />

    <Button controls:DockPanel.Dock="Right" Content="#4" />

</controls:DockPanel>

image

So, Button #1 is docked first to the bottom area, followed by buttons #2 and #3, and finally Button #4 is docked to the Right.

Let’s put more items on the Right docking area.

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Bottom" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

    <Button controls:DockPanel.Dock="Bottom" Content="#3" />

    <Button controls:DockPanel.Dock="Right" Content="#4" />

    <Button controls:DockPanel.Dock="Right" Content="#5" />

    <Button controls:DockPanel.Dock="Right" Content="#6" />

</controls:DockPanel>

image

Continuing for where the last sample left off, Button #4 is the first control docked to the right, followed by Button #5 and finally Button #6.

And we’ll finish this sample by adding Top docked buttons and Left docked buttons.

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Bottom" Content="#1" />

    <Button controls:DockPanel.Dock="Bottom" Content="#2" />

    <Button controls:DockPanel.Dock="Bottom" Content="#3" />

    <Button controls:DockPanel.Dock="Right" Content="#4" />

    <Button controls:DockPanel.Dock="Right" Content="#5" />

    <Button controls:DockPanel.Dock="Right" Content="#6" />

    <Button controls:DockPanel.Dock="Top" Content="#7" />

    <Button controls:DockPanel.Dock="Top" Content="#8" />

    <Button controls:DockPanel.Dock="Top" Content="#9" />

    <Button controls:DockPanel.Dock="Left" Content="#10" />

    <Button controls:DockPanel.Dock="Left" Content="#11" />

    <Button controls:DockPanel.Dock="Left" Content="#12" />

</controls:DockPanel>

image

First, Buttons #1, #2 & #3 Get placed on the bottom.

Second, Buttons #4, #5 & #6 get placed on the right, using up remaining height in the DockPanel.

Third, Buttons #7, #8 & #9 get placed on the top, using up remaining width in the DockPanel.

Lastly, Buttons #10, #11 & #12 get placed on the Left, using up remaining Height in the DockPanel (after placing both Bottom and Top buttons).

 

So again – The order of DockPanel Children’s determines their placement based on precedence.

Let’s mix it up a bit by alternating top buttons and left buttons.

<controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Bottom" Content="#1" />

    <Button controls:DockPanel.Dock="Right" Content="#2" />

    <Button controls:DockPanel.Dock="Bottom" Content="#3" />

    <Button controls:DockPanel.Dock="Right" Content="#4" />

    <Button controls:DockPanel.Dock="Bottom" Content="#5" />

    <Button controls:DockPanel.Dock="Right" Content="#6" />

</controls:DockPanel>

image

image 

We can see that items are weaved into the DockPanel, based on their order.

 

 

Spiral Sample

One last final sample for DockPanel is the Spiral sample by Ted Glaza (a developer on the Silverlight Toolkit team) and slightly changed for this blog post.

 <controls:DockPanel LastChildFill="False">

    <Button controls:DockPanel.Dock="Left" Background="LightBlue" Content="#1" />

    <Button controls:DockPanel.Dock="Top" Background="LightCoral" Content="#2" />

    <Button controls:DockPanel.Dock="Right" Background="LightGreen" Content="#3" />

    <Button controls:DockPanel.Dock="Bottom" Background="LightYellow" Content="#4" />

    <Button controls:DockPanel.Dock="Left" Background="LightGreen" Content="#5" />

    <Button controls:DockPanel.Dock="Top" Background="LightYellow" Content="#6" />

    <Button controls:DockPanel.Dock="Right" Background="LightBlue" Content="#7" />

    <Button controls:DockPanel.Dock="Bottom" Background="LightCoral" Content="#8" />

    <Button controls:DockPanel.Dock="Left" Background="LightGray" Content="#9" />

    <Button controls:DockPanel.Dock="Top" Background="LightCoral" Content="#10" />

    <Button controls:DockPanel.Dock="Right" Background="LightGreen" Content="#11" />

    <Button controls:DockPanel.Dock="Bottom" Background="LightBlue" Content="#12" />

    <Button controls:DockPanel.Dock="Left" Background="LightCoral" Content="#13" />

    <Button controls:DockPanel.Dock="Top" Background="LightGoldenrodYellow" Content="#14" />

    <Button controls:DockPanel.Dock="Right" Background="LightYellow" Content="#15" />

    <Button controls:DockPanel.Dock="Bottom" Background="LightGreen" Content="#16" />

    <Button controls:DockPanel.Dock="Left" Background="LightYellow" Content="#17" />

    <Button controls:DockPanel.Dock="Top" Background="LightCoral" Content="#18" />

    <Button controls:DockPanel.Dock="Right" Background="LightBlue" Content="#19" />

    <Button controls:DockPanel.Dock="Bottom" Background="LightGreen" Content="#20" />

    <Button controls:DockPanel.Dock="Left" Background="LightBlue" Content="#21" />

    <Button controls:DockPanel.Dock="Top" Background="LightGreen" Content="#22" />

    <Button controls:DockPanel.Dock="Right" Background="LightCoral" Content="#23" />

    <Button controls:DockPanel.Dock="Bottom" Background="LightYellow" Content="#24" />

</controls:DockPanel>

image

image

Pretty, isn’t it?

 

-- Justin Angel

Microsoft Silverlight Program Manager

Posted by JustinAngel | 7 comment(s)
Filed under:

Silverlight Toolkit: Label

Hi Folks,

 

I’d like for us to talk a bit a seemingly simple control in the Silverlight Toolkit – Label.

In the following article we’ll deep dive into the many nooks and crannies Label has and unleash some of it’s true power.

 

Setup

1. Create a new project.

image

 

2, Add a reference to the Silverlight Controls assembly (Microsoft.Windows.Controls.dll) which can be downloaded at http://codeplex.com/Silverlight.

image   image

 

3. Look under "Custom Controls" In the Blend Asset Library.

image

 

4. Add a Label to the Page.

image

And here's the XAML we got:

<UserControl

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    x:Class="SilverlightControlsNovember2008.Page"

    Width="640" Height="480"

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

    <Grid x:Name="LayoutRoot" Background="White">

        <slctls:Label HorizontalAlignment="Left" Margin="98,179,0,220" Width="148" Content="Label"/>

    </Grid>

</UserControl>

 

 

Setting the content for Label

One way of editing a Label's content is double clicking on it.

image

image

And here's the XAML we just got:

<slctls:Label HorizontalAlignment="Left" Margin="98,179,0,220" Width="148" Content="Hello World!"/>

 

Another way is editing the Content property directly through the Blend Data pane:

 image

 

 

Changing the Label’s Border

We can set the BorderBrush & BorderThinckness properties for Label in order to change it’s border.

image

 

Let’s start by changing the BorderBrush to a SoliderColorBrush with a light grey color. Click on BorderBrush and select SolidColorBrush.

image --> image

Than we’ll select a light gray color.

image

 

Next, we’ll change the BorderThickness to 1 on all sides.

image

 

And we can see our Label has a nice subtle light grey border around itself:

image

 

Here’s the XAML we just generated:

<slctls:Label HorizontalAlignment="Left" Margin="98,179,0,0" Width="79" Content="I am a Label!" VerticalAlignment="Top" Height="20" BorderBrush="#FFC6C4C4" BorderThickness="1,1,1,1"/>

 

 

Changing Label’s Background and Foreground

Let’s do what the title says!

In case you’re wondering TextBlock does not have a Background. So it’s a bit different than what we would have normally done with TextBlock.

 

We’ll select Background and set it to SolidColorBrush with the color Black.

image -->image

image

 

Next we’ll select the Foreground property and set it to SolidColorBrush with the color white.

image -->image

 

here’s our Label:

image

And the xaml we generated:

<slctls:Label HorizontalAlignment="Left" Margin="98,179,0,0" Width="79" Content="I am a Label!" VerticalAlignment="Top" Height="20" BorderBrush="#FFC6C4C4" BorderThickness="1,1,1,1" Background="#FF000000" Foreground="#FFF5F3F3"/>

 

Changing the Label’s Template

Let’s say we're unhappy with the default border for out Text inside the Label. Through the power of templating we can change it.
So let’s create a RadialLabelTemplate.

 

We’ll start of by adding a new label to form.

image

Than Right Click on it, select “Edit Control Parts(Template) –> Create Empty…”.

image

We’ll change the Resource name to RadialPanelTemplate.

image

And here’s the drawing area of the new template:

image

Let’s add the Ellipse for the radial background.

image

image

Now we want to add a TextBlock to display the content of the Label. Before we can do that, we’ll need to add a container that will contain both our Ellipse and our TextBlock. We’ll Group our Ellipse into a Canvas.

image

image

 

Finally we can add our TextBlock that has the Label Content.

image

image

 

We’ll use TemplateBinding to connect this TextBlock.Text to the Label.Content property. Click the “Advanced Options” next to the Text property.

image

Select “Custom Expression”.

image

And put in the correct TemplateBinding.

image

 

To preview our form we can go back to our form.

image

 

And here it is:

image

 

Now we can we add 3 more label to our page and just apply this new template to them.

image

We’ll select each of our new Labels, Right click, select “Edit Control Parts (Template) –> Apply Resource –> Radial Label Template”.

 image -

And here’s our new form:

image

 

Here’s the XAML we just generated for the RadialLabelTemplate:

    <UserControl.Resources>

       <ControlTemplate x:Key="RadialLabelTemplate" TargetType="slctls:Label">

            <Canvas Height="Auto" Width="Auto">

                <Ellipse Height="35" Width="125" Fill="#FFFFFFFF" Stroke="#FF000000"/>

                <TextBlock Height="20" Width="82.667" Canvas.Left="22.667" Canvas.Top="7.333" Text="{TemplateBinding Content}" TextWrapping="Wrap"/>

            </Canvas>

        </ControlTemplate>

    </UserControl.Resources>

And the Xaml for our labels:

<slctls:Label Template="{StaticResource RadialLabelTemplate}" Content="Radial Label!" Width="124"  Height="34"/>

<slctls:Label Template="{StaticResource RadialLabelTemplate}" Height="19.333" Content="Radial  == good" FontSize="10"/>

<slctls:Label Template="{StaticResource RadialLabelTemplate}" Height="29.333" Width="144" Content="I R Radial" />

<slctls:Label Template="{StaticResource RadialLabelTemplate}" Height="28.667" Width="130.334" Content="U R Radial"/>

 

 

Editing a Label’s ContentTemplate

Templates are used with TemplateBindings that emanate for general Control properties. But we might do bind our Label to CLR property from any Data Source. like, Cows.

image

We’ll create (in Visual studio) our Cow class that has Age and Name.

    public class Cow

    {

        public Cow(string Name, int Age)

        {

            Name = Name;

            Age = Age;

        }

 

        public string Name { get; set;  }

        public int Age { get; set;  }

    }

A very basic CLR class that has 2 properties: a numeric age and a string that represents the age of the cow.

Now let’s use this class and create a cow we’ll DataBind our label to.

    public partial class Page : UserControl

    {

        public Page()

        {

            // Required to initialize variables

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Page_Loaded);

        }

 

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            myLabel.DataContext = new Cow("Betsy", 3);

        }

    }

 

Eventually I’d like for us to see a Label that looks like this:

image

We’d like to change the thickness of the head line based on Cow.Age and change the text based on Cow.Name.

 

Let’s start by adding a new Label to the page and changing it’s name to myLabel.

image

We’d like to edit the ContentTemplate of this label, so we’ll Right Click on the label select “Edit Other Templates –> Edit Generated Content (ContentTemplate) –> Create Empty…”

 

image

We’ll call our new ContentTemplate – CowContentTemplate.

image

As always we start off with an empty ContentTemplate.

image

I’ll spare you my third grade drawing skills and we’ll magiclly add some lines that are our cow.

image

Truly a masterpiece.

Single cowIf you squint really hard, they look alike 

Next we’d like to add the appropriate bindings.

We’ll select the TextBlock in the middle of the cow.

 

image

Click “Advanced Options –> Custom Expression”.

image

image

And add a Binding to the Cow Name.

image

 

Next, we’ll select the Cow’s head.

image

And set a StrokeThickness to a Custom expression that’s bound to the Cow’s age.

image

 

One last thing we have to do before we can run the sample is set the Cow’s Content to it’s DataContext.

image

We’ll ad a Custom expression to the Content property of the label.

image

 

Finally we can run the sample.

image

Let’s add a few more Labels with that ContentTemplate and with more Cows.

public partial class Page : UserControl

{

    public Page()

    {

        // Required to initialize variables

        InitializeComponent();

        this.Loaded += new RoutedEventHandler(Page_Loaded);

    }

 

    void Page_Loaded(object sender, RoutedEventArgs e)

    {

        myLabel.DataContext = new Cow("Betsy", 3);

        myCowLabel1.DataContext = new Cow("Martha", 1);

        myCowLabel2.DataContext = new Cow("Flossy", 5);

        myCowLabel3.DataContext = new Cow("Hoss", 2);

    }

}

We’ll make sure to add those label to our page and re-run this sample.

image

And our Cow Herd is now complete.

 

Here’s our DataTemplate XML.

<UserControl.Resources>

    <DataTemplate x:Key="CowContentTemplate">

        <Grid>

            <TextBlock Margin="21.75,9.833,27.25,9.167" TextWrapping="Wrap" FontSize="8" Text="{Binding Path=Name}"/>

            <Ellipse HorizontalAlignment="Right" Margin="0,2.167,4.583,13.833" Width="15.084" Fill="#FFFFFFFF" Stroke="#FF000000" StrokeThickness="{Binding Path=Age}"/>

            <Rectangle Margin="18.75,8,25.25,8" Fill="#FFFFFFFF" Stroke="#FF000000" RadiusX="1" RadiusY="1"/>

            <Path Height="2.334" HorizontalAlignment="Right" Margin="0,12.25,19.417,0" VerticalAlignment="Top" Width="6.667" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M65.166664,9.833333 L59.5,11.166667"/>

            <Path Height="6" HorizontalAlignment="Right" Margin="0,0,23.75,2.667" VerticalAlignment="Bottom" Width="3.667" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M58.833332,19.666666 L61.5,24.666666" d:LayoutOverrides="Width"/>

            <Path Height="4.5" HorizontalAlignment="Left" Margin="27.585,0,0,3.833" VerticalAlignment="Bottom" Width="2.166" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M35.333332,19.666666 L34.166668,23.166666"/>

            <Path Height="4.834" HorizontalAlignment="Right" Margin="0,0,33.751,4.333" VerticalAlignment="Bottom" Width="1.833" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M51.833332,22.666666 L51,18.833334" d:LayoutOverrides="Width"/>

            <Path Height="5" HorizontalAlignment="Left" Margin="18.917,0,0,4.333" VerticalAlignment="Bottom" Width="4" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M27.333334,19.35417 L24.833334,23.187502"/>

        </Grid>

    </DataTemplate>

</UserControl.Resources>

 

And our Cow labels:

<slctls:Label Height="32.5" Margin="311.5,56.75,235.5,0" VerticalAlignment="Top" x:Name="myLabel" ContentTemplate="{StaticResource CowContentTemplate}" Content="{Binding}"  />

<slctls:Label Height="32.5" Margin="311,129.5,236,0" VerticalAlignment="Top" x:Name="myCowLabel1" ContentTemplate="{StaticResource CowContentTemplate}" Content="{Binding}" />

<slctls:Label Height="32.5" Margin="311,198.75,236,0" VerticalAlignment="Top" x:Name="myCowLabel2" ContentTemplate="{StaticResource CowContentTemplate}" Content="{Binding}"  />

<slctls:Label Height="32.5" Margin="311.5,0,235.5,184.5" x:Name="myCowLabel3" ContentTemplate="{StaticResource CowContentTemplate}" Content="{Binding}"  />

 

 

-- Justin-Josef Angel

Microsoft Silverlight Program Manager

Silverlight Toolkit November 2008 Overview

Hi folks,

 

We’ve just shipped the first release of the Silverlight Toolkit’s on http://codeplex.com/Silverlight.

HelloWorld1

HelloWorld2

HelloWorld3  

HelloWorld4

 

I’d like to do a 101 technical overview of these controls in this blog post.

During the next few days I’ll publish technical deep dives on each control, but for now, we’re sticking to an overview.

 

TreeView 

TreeView

<controls:TreeView Width="150" Height="200">

    <controls:TreeViewItem Header="You" IsExpanded="True">

        <controls:TreeViewItem Header="Work" IsExpanded="True">

            <controls:TreeViewItem Header="Silverlight" IsExpanded="True"/>

        </controls:TreeViewItem>

        <controls:TreeViewItem Header="Life" IsExpanded="True">

            <controls:TreeViewItem Header="Family"/>

            <controls:TreeViewItem Header="Friends"/>

        </controls:TreeViewItem>

    </controls:TreeViewItem>

</controls:TreeView>

 

Let’s review what’s going on here.

We’ve nested some TreeViewItems in one another (Which implicitly set the TreeView.Items property) and set TreeView.IsExpanded=True to show those children up once the Treeview loads. One more interesting thing we’ve done is set the TreeView.Header property (which could have been populated with any element since it’s just Content).

 

AutoCompleteBox

AutoCompleteBox

<controls:AutoCompleteBox Width="100" x:Name="autoComplete" />

 

autoComplete.ItemsSource = new string[]

        {"You", "Life", "Work", "Silverlight", "Friends", "Family"};

 

By Setting the AutoComplete.ItemsSource we’ve told the AutoComplete to filter out items from this list of items.

In future blog posts we’ll see how we can change the display of the drop down and the filtering behavior.

 

NumericUpDown

NumericUpDown

<input:NumericUpDown Width="100" Height="30" Increment="1" IsEditable="True" Maximum="100" Minimum="0" Value="33" DecimalPlaces="1"/>

 

The property names are pretty self explanatory. Interesting to note is the NumericUpDown.DecimalPlaces property that let’s you define how many decimal places after the dot you’d like to show in your NumericUpDown.

 

DockPanel

DockPanel 

<Border Height="Auto" Width="Auto" BorderBrush="#FF000000" BorderThickness="1,1,1,1" >

    <controls:DockPanel Height="150" Width="200" LastChildFill="True">

        <Image Source="You.png" controls:DockPanel.Dock="Left" Stretch="None"/>

        <Image Source="Work.png" controls:DockPanel.Dock="Right" Stretch="None"/>

        <Image Source="Family.png" controls:DockPanel.Dock="Top" Stretch="None"/>

        <Image Source="Friends.png" controls:DockPanel.Dock="Bottom" Stretch="None"/>

        <Image Source="Life.png" Stretch="None" />

    </controls:DockPanel>

</Border>

To begin with, you can see that the DockPanel is surrounded with a <Border /> just so we could see the edges of the DockPanel.

Next you can see that each Image is placed in it’s original size on the DockPanel and each Docked with the DockPanel.Dock Attached Dependency property to a different side.

And last, the DockPanel.LastChildFill is set to true. So the last item will be aligned to the “Center” dock. Since the image is marked as “No Stretch” it won’t expand, but it’s still aligned to center.

 

 

WrapPanel

WrapPanel

<controls:WrapPanel Orientation="Horizontal" Width="200">

    <Image Source="Life.png" Stretch="None" />

    <Image Source="You.png" Stretch="None" />

    <Image Source="Work.png" Stretch="None" />

    <Image Source="Family.png" Stretch="None" />

    <Image Source="Friends.png" Stretch="None" />

    <Image Source="Silverlight.png" Stretch="None" />

</controls:WrapPanel>

 

For those of you familiar with WrapPanel it’s pretty obvious what’s going on here – there’s a bunch of items being written sequentially  left-to-right and than to the next row.

 

Let’s test this WrapPanel out in different widths: 50, 100 and 200 pixels width.

Same WrapPanel Width=50

image

Width=100

image

 

Width=150

image

And finally Width=200.

WrapPanel

The interesting thing about this sample is that it’s aligned Left-to-Right because we’ve set WrapPanel.Orientation=Horizontal.
We could have changed it to Vertical so the WrapPanel would place items top-to-bottom.

 

 

ViewBox

Viewbox 

<controls:Viewbox Height="50" Width="20">

    <Image Source="StickMan.png" Height="100" Width="40"/>

</controls:Viewbox>

<controls:Viewbox Height="100" Width="40">

    <Image Source="StickMan.png" Height="100" Width="40" />

</controls:Viewbox>

<controls:Viewbox Height="150" Width="100">

    <Image Source="StickMan.png" Height="100" Width="40"/>

</controls:Viewbox>

 

A ViewBox essentially resized content to fit it by applying a ScaleTransform.

So in the first sample, where we have a 40x100 pixels image in a 20x50 pixels viewbox – The Image would get a ScaleTransform of 0.5. (50%)

In the second sample, where the container is exactly 40x100 pixels wide, we’ll get a ScaleTransform of 1 (100%, meaning none).

And in the Third sample, where the container is 150x100 pixels wide we’ll get a ScaleTansform of all more than 1.5 (more than 150%).

 

Label

Label

<controls:Label FontSize="18">

    <StackPanel Orientation="Horizontal">

        <Image Source="You.png" />

        <TextBlock Text="I'm a Stickperson!"/>

    </StackPanel>

</controls:Label>

 

Label isn’t a really intriguing control, but it has one very appealing property. Instead of plain text, it has Label.Content property.
Which is one of the strengths of WPF/Silvelright based model in comparison to more mature ASP.Net/Winforms based models.

In this Label we’ve decided to place a TextBlock and an Image horizontally aligned inside a Label.

The beauty here is that we’ve declared the Label as Font 18 and that tunneled down all the way to TextBlock.

 

HeaderedContentControl

HeaderedContentControl

<controls:HeaderedContentControl HorizontalContentAlignment="Center">

    <controls:HeaderedContentControl.Header>

        <TextBlock Text="Your Stickfigure life" FontSize="18" TextDecorations="Underline" />

    </controls:HeaderedContentControl.Header>

    <controls:HeaderedContentControl.Content>

        <Image Source="Life.png" Stretch="None" />

    </controls:HeaderedContentControl.Content>

</controls:HeaderedContentControl>

The HeaderedContentControl has two interesting properties we’re showing off here – HeaderedContentControl.Content and HeaderedContentControl.Header.

Both of which follow the “content” model and can be set to any element.

In this sample we’ve placed a TextBlock into the Header and an Image in the Content.

 

 

Expander

image

<controls:Expander>

    <controls:HeaderedContentControl.Header>

        <TextBlock Text="Your Stickfigure life" FontSize="18" TextDecorations="Underline" />

    </controls:HeaderedContentControl.Header>

    <controls:HeaderedContentControl.Content>

        <Image Source="Life.png" Stretch="None" />

    </controls:HeaderedContentControl.Content>

</controls:Expander>

 

The Expander control inherits from HeaderedContentcontrol so it has roughly the same API.

But, it renders out a completely different control.

This is how Expander looks like once it’s loaded:

image

And with one click on the Expand button, it drops down.

image

Another click brings it back to it’s collapsed state.

image

 

HeaderedItemControl

HeaderedItemsControl

headeredItemControl.ItemsSource = new string[]

    { "You", "Life", "Work", "Silverlight", "Friends", "Family" };

 

<controls:HeaderedItemsControl x:Name="headeredItemControl">

    <controls:HeaderedItemsControl.Header>

        <TextBlock Text="Your life" FontSize="18" TextDecorations="Underline" />

    </controls:HeaderedItemsControl.Header>

    <controls:HeaderedItemsControl.ItemTemplate>

        <DataTemplate>

            <TextBlock Text="{Binding}" Margin="10 0 0 0"/>

        </DataTemplate>

    </controls:HeaderedItemsControl.ItemTemplate>

</controls:HeaderedItemsControl>

The HeaderedItemsControl is an ItemsControl that has a HeaderedItemscontrol.Header property.

we’ll set the Header property with a TextBlock.

Now, we’ve defined a HeaderedItemsControl.ItemsTemplate that basically shows us whatever you bind to it in a TextBlock with some margin.

We’ve given the sample a list of value as the HeaderedItemsControl.ItemsSource and it rendered all of those into the TextBlocks found in the ItemTemplate.

 

 

Chart - ColumnSeries

ColumnSeries

columnSeries.DataContext = new KeyValuePair<string, int>[]

                               {

               new KeyValuePair<string, int>("Work", 9),

               new KeyValuePair<string, int>("Sleep", 8),

               new KeyValuePair<string, int>("Driving", 2),

               new KeyValuePair<string, int>("Family", 4),

               new KeyValuePair<string, int>("Friens", 1),

                               };

<charting:Chart x:Name="columnSeries" Height="200" Margin="8,8,492,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="300">

    <charting:Chart.Series>

        <charting:ColumnSeries ItemsSource="{Binding}"

                              DependentValueBinding="{Binding Value}"

                              IndependentValueBinding="{Binding Key}"

                              Title="Time"  />

    </charting:Chart.Series>

</charting:Chart>

 

Let’s explain what we’re seeing and how we got to it.

First, we’ve got a Chart with a Chart.Series set to ColumnSeries. That by itself is enough t add a new ColumnSeries to the chart.

Now, we want some data in our Chart and we’ll use DataBinding magic to get it.

We’ll start off by specifying a Chart.DataContext with a collection of KeyValuePairs. Each pair has a Key and a Value.
Next, we’ll tell the ColumnSeries.DependentValue (which is the numerical value being followed on the columns) that it’s DataBound to Value.
And DataBind ColumnSeries.IndependentValue to Key.

It’s important to remember that, IndependentValue is the text that shows up on under the Column. And DependentValue is the value of the actual Column.

We’ll put the Cherry on top by specifying ColumnSeries.Title as ‘Time’. 

 

 

Chart - BarSeries

BarSeries

barSeries.DataContext = new KeyValuePair<string, int>[]

                               {

               new KeyValuePair<string, int>("Work", 9),

               new KeyValuePair<string, int>("Sleep", 8),

               new KeyValuePair<string, int>("Driving", 2),

               new KeyValuePair<string, int>("Family", 4),

               new KeyValuePair<string, int>("Friens", 1),

                               };

<charting:Chart x:Name="barSeries" Width="350" Height="250">

    <charting:Chart.Series>

        <charting:BarSeries ItemsSource="{Binding}"

                           DependentValueBinding="{Binding Path=Value}"

                           IndependentValueBinding="{Binding Path=Key}"

                           Title="Life" />

    </charting:Chart.Series>

</charting:Chart>

Very similar to the ColumnSeries example, just that in this example we’ll use a BarSeries.

 

 

Chart – PieSeries

PieSeries

pieSeries.DataContext = new KeyValuePair<string, int>[]

                               {

               new KeyValuePair<string, int>("Work", 9),

               new KeyValuePair<string, int>("Sleep", 8),

               new KeyValuePair<string, int>("Driving", 2),

               new KeyValuePair<string, int>("Family", 4),

               new KeyValuePair<string, int>("Friens", 1),

                               };

<charting:Chart x:Name="pieSeries" Width="350" Height="250">

    <charting:Chart.Series>

        <charting:PieSeries ItemsSource="{Binding}"

                           DependentValueBinding="{Binding Path=Value}"

                           IndependentValueBinding="{Binding Path=Key}"

                           Title="Life"/>

    </charting:Chart.Series>

</charting:Chart>

Again, very similar to the BarColumn Sample. We’re just using a PieSeries here.

 

 

Chart - ScatterSeries

ScatterSeries

scatterSeries.DataContext = new KeyValuePair<DateTime, int>[] {

       new KeyValuePair<DateTime, int>(DateTime.Now, 9),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(1), 8),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(2), 9),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(3), 6),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(4), 8)

    };

<charting:Chart x:Name="scatterSeries" Width="400" Height="250" >

    <charting:Chart.Series>

        <charting:ScatterSeries ItemsSource="{Binding}"

                               DependentValueBinding="{Binding Path=Value}"

                               IndependentValueBinding="{Binding Path=Key}"

                               Title="Work" />

    </charting:Chart.Series>

</charting:Chart>

 

Let’s look at the chart. It shows how many hours we’ve worked each day in the week.

The reason this Chart is different than the previous charts is that a ScatterSeries.IndepdenValue needs to be comparable.
The Chart orders items based on their relative “size” in comparison to other items. In previous examples, the order of items determined final horizontal placement. However, In this type of series, The value of the IndepdentValue determines that.

So Instead of using a string which isn’t comparable and does not work as an IndependentValue, we’re using a DataTime.

The rest is pretty similar to how we’ve worked with other charts.

 

 

Chart – Line Series

LineSeries 

lineSeries.DataContext = new KeyValuePair<DateTime, int>[] {

       new KeyValuePair<DateTime, int>(DateTime.Now, 9),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(1), 8),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(3), 6),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(2), 9),

       new KeyValuePair<DateTime, int>(DateTime.Now.AddDays(4), 8)

    };

<charting:Chart x:Name="lineSeries" Width="400" Height="250" >

    <charting:Chart.Series>

        <charting:LineSeries ItemsSource="{Binding}"

                            DependentValueBinding="{Binding Path=Value}"

                            IndependentValueBinding="{Binding Path=Key}"

                            Title="Work"/>

    </charting:Chart.Series>

</charting:Chart>

This is pretty similar to how we’ve worked with ScatterSeries, just that in this case we’re using a LineSeries.

A LineSeries is visually equivalent to a ScatterSeries, minus the fact that it has lines drawn between it’s DataPoints.

 

 

ImplicitStyleManager

ImplicitStyleManager

// in myPage.xaml

<UserControl theming:ImplicitStyleManager.ApplyMode="OneTime"

   theming:ImplicitStyleManager.ResourceDictionaryUri="projectName;compoent/Theme.xaml" >

    <Button Content="Hello Stickperson!" Canvas.Top="170" Canvas.Left="191" />

</UserControl>

// in Theme.xaml

<ResourceDictionary

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >

    <Style TargetType="Button">

        <Setter Property="FontSize" Value="22" />

        <Setter Property="Foreground" Value="Blue" />

    </Style>

</ResourceDictionary>

 

As you can see, in Theme.xaml we’ve got a default style for Button. A default style basically means “we want all controls of type X to receive style Y as default”.

In this specific sample we want all Buttons by default to be Font size 22 and foreground color Blue.

 

Now in this sample ImplicitStyleManager takes the Theme.xaml file, loads it up and applies it to all the children of UserControl.
We instructed it to do that by specifying an ImplicitStyleManager.ResourceDictionaryUri property with the full resource URI for Theme.xaml. And we made sure Theme.xaml has a built action set to Resource.

We’ve also specified ImplicitStyleManager.ApplyMode=OneTime which just means that we want the styles to be applied on the UserControl.Loaded event and not apply styles to new controls which are added later on.

 

 

Expression Light Theme

ExpressionDarkTheme 

<expressionDark:ExpressionDarkTheme>

    <StackPanel Margin="5">

        <Button Margin="5" Content="Hello Stickperson!"/>

        <ComboBox Margin="5">

            <ComboBoxItem Content="Mr. Stickman" IsSelected="True"/>

        </ComboBox>

        <CheckBox Content="Are you a StickPerson?"/>

        <Slider Margin="5"/>

        <input:NumericUpDown Width="50" Margin="5"/>

    </StackPanel>

</expressionDark:ExpressionDarkTheme>

This is a pretty straight forward sample. We’ve shipped 6 Silverlight Themes with the Silverlight Toolkit.
ExpressionDarkTheme is one of those.

After adding a reference to the correct DLL we can just set our top level container as the Theme Control and all nested controls would get the Expression Dark Theme.

 

ExpressionLightTheme

ExpressionLightTheme

<expressionLight:ExpressionLightTheme>

    <StackPanel Margin="5">

        <Button Margin="5" Content="Hello Stickperson!"/>

        <ComboBox Margin="5">

            <ComboBoxItem Content="Mr. Stickman" IsSelected="True"/>

        </ComboBox>

        <CheckBox Content="Are you a StickPerson?"/>

        <Slider Margin="5"/>

        <input:NumericUpDown Width="50" Margin="5"/>

    </StackPanel>

</expressionLight:ExpressionLightTheme>

 

 

RainierOrangeTheme

RainierOrangeTheme 

<rainerOrange:RainierOrangeTheme>

    <StackPanel Margin="5">

        <Button Margin="5" Content="Hello Stickperson!"/>

        <ComboBox Margin="5">

            <ComboBoxItem Content="Mr. Stickman" IsSelected="True"/>

        </ComboBox>

        <CheckBox Content="Are you a StickPerson?"/>

        <Slider Margin="5"/>

        <input:NumericUpDown Width="50" Margin="5"/>

    </StackPanel>

</rainerOrange:RainierOrangeTheme>

 

 

RainierPurpleTheme

RainierPurpleTheme 

<rainerPurple:RainierPurpleTheme>

    <StackPanel Margin="5">

        <Button Margin="5" Content="Hello Stickperson!"/>

        <ComboBox Margin="5">

            <ComboBoxItem Content="Mr. Stickman" IsSelected="True"/>

        </ComboBox>

        <CheckBox Content="Are you a StickPerson?"/>

        <Slider Margin="5"/>

        <input:NumericUpDown Width="50" Margin="5"/>

    </StackPanel>

</rainerPurple:RainierPurpleTheme>

 

 

ShinyBlueTheme

ShinyBlueTheme 

<shinyBlue:ShinyBlueTheme>

    <StackPanel Margin="5">

        <Button Margin="5" Content="Hello Stickperson!"/>

        <ComboBox Margin="5">

            <ComboBoxItem Content="Mr. Stickman" IsSelected="True"/>

        </ComboBox>

        <CheckBox Content="Are you a StickPerson?"/>

        <Slider Margin="5"/>

        <input:NumericUpDown Width="50" Margin="5"/>

    </StackPanel>

</shinyBlue:ShinyBlueTheme>

 

 

ShinyRedTheme

ShinyRedTheme 

<shinyRed:ShinyRedTheme>

    <StackPanel Margin="5">

        <Button Margin="5" Content="Hello Stickperson!"/>

        <ComboBox Margin="5">

            <ComboBoxItem Content="Mr. Stickman" IsSelected="True"/>

        </ComboBox>

        <CheckBox Content="Are you a StickPerson?"/>

        <Slider Margin="5"/>

        <input:NumericUpDown Width="50" Margin="5"/>

    </StackPanel>

</shinyRed:ShinyRedTheme>

 

 

 

-- Justin Angel

Microsoft Silverlight Program Manager

Posted by JustinAngel | 4 comment(s)
Filed under: