Page view counter

Tour around Silverlight Contrib

I’m a huge supporter of open source software development and I'd like to take this opportunity to go over the Silverlight Contrib O/S project.

Fair disclosure first though, my current role is Program Manager for the Silverlight Toolkit team which ships on codeplex (at http://www.codeplex.com/Silverlight). 
I’ve got a very high quality bar and I expect nothing less from any O/S project that I ask customers to put into their technology stack.

Standard Microsoft disclaimer: KGB Assassins will be hired toWait, other Disclaimer: I do not speak for my employer.

 

Getting Started

OK, this is straight forward and well-organized.

Codeplex website @ http://www.codeplex.com/SilverlightContrib.
I went to the Release Tab and downloaded the latest Alpha 3 release from December 15th.

Official Website @ http://SilverlightContrib.org.

And live demo @ http://silverlightcontrib.org/demo/.

Silverlight Contrib Demo App

First impressions is really important, especially in a open source projects. A real problem that plagues open source initiatives is the lack of proper documentation and support.
Silverlight Contrib has an excellent first impression. Excellent website organization, solid sample app, and it even comes with a CHM file!

image

Unfortunately some of the subjects in the CHM file clearly say they’re missing documentation:

image

 

OK, Let’s start a new SIlverlight Application and add the (3?) Silverlight Contrib DLLs.

image

image 

image

And here’s how our solution looks like after we added the DLLs:

image

 

Inside the XAML editor, we’ll go to “Choose Items” and add the “SilverlightContrib.Controls.dll” to the Visual Studio Toolbox:

image    --> image

 

 

Color Picker

Ok, enough fooling around. Let’s build something. We’ll start from the Color Picker.

Based on the CHM file here’s what we’ve got In ColorPicker:

image

We’ve got a ColorSelected event and a SelectedColor property.

Let’s build a simple app that has a color picker and a rectangle that uses that colour as fill.

<UserControl x:Class="SL_Contrib.Page"

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

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

   xmlns:SilverlightContrib="clr-namespace:SilverlightContrib.Controls;assembly=SilverlightContrib.Controls"

   Width="400" Height="200">

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

        <SilverlightContrib:ColorPicker x:Name="colorPicker" Width="200" Height="200" SelectedColor="Green" />

        <Rectangle x:Name="myRect" Fill="Green" Width="100" Height="100" />

    </StackPanel>

</UserControl>

Hmm… I was writing the event registration there for a second and got confused… Why is the Property called “SelectedColor” and the change event called “ColorChanged”? Shouldn’t it be “SelectedColorChanged”? Minor annoyance, but still.

    public partial class Page : UserControl

    {

        public Page()

        {

            InitializeComponent();

            colorPicker.ColorSelected += new ColorSelectedHandler(colorPicker_ColorSelected);

        }

 

        private void colorPicker_ColorSelected(object sender, ColorSelectedEventArgs e)

        {

            myRect.Fill.As<SolidColorBrush>().Color = e.SelectedColor;

        }

    }

 

    public static class Extensions

    {

        public static T As<T>(this object obj)

        {

            return (T) obj;

        }

    }

(I’ve added my As<T> extension method)

Let’s run this sample:

image

Truly a master-piece app.

Yep, and when we select another color the rectangle gets updated.

image image image

It looks like the ColorPicker isn’t invoking the ColorChanged event when you just drag & drop…

image image

You can see that the in the first picture I’ve started dragging and the second picture is while still dragging.
The control visuals get updated, but there’s no external event you can use to pick up on that until the user drops and release the mouse capture.

 

The TextBlock on the bottom left isn’t editable, so we’ll create another TextBox and try to change the selected colour.

<SilverlightContrib:ColorPicker x:Name="colorPicker" Width="200" Height="200" SelectedColor="Green" />

<TextBox x:Name="tbxColour" />

<Button x:Name="btnCommit" Content="Change colour" />

<Rectangle x:Name="myRect" Fill="Green" Width="100" Height="100" />

   

    public Page()

    {

        InitializeComponent();

        colorPicker.ColorSelected += new ColorSelectedHandler(colorPicker_ColorSelected);

        btnCommit.Click += new RoutedEventHandler(btnCommit_Click);

    }

 

    void btnCommit_Click(object sender, RoutedEventArgs e)

    {

        byte alpha = Convert.ToByte(tbxColour.Text.Substring(0, 2), 16);

        byte red = Convert.ToByte(tbxColour.Text.Substring(2, 2), 16);

        byte green = Convert.ToByte(tbxColour.Text.Substring(4, 2), 16);

        byte blue = Convert.ToByte(tbxColour.Text.Substring(6, 2), 16);

        colorPicker.SelectedColor = Color.FromArgb(alpha, red, green, blue);

    }

And when we run our sample:

imageimage

Works like a charm.

 

I’ve opened the application in Blend to try and change the default layout of the ColorPicker.

image

Now, I changed the default visual tree for this control to move the Hue selector from the left to the right and viola:

image

Still works like a charm:

image

One cool thing though that I’ve noticed in Blend is how the nice spectrum is built:

image

It’s basically a Gradient with a bunch of GradientStops. cool stuff. I keep being amazed by how people use the basic 2d drawing abilities of Silverlight.

 

 

 

All and all, this is a very cool control.

Pros:

  1. Very cool visuals appearance. Main color selection palette, side spectrum selection palette and an area that shows the currently selected color and it’s Hex.
  2. Solid control.

Minor cons:

  • The event naming for “ColorChanged” is not consistent with the property name “SelectedColor”.
  • No event “ColorChanging” that fired while the eye dropper is being dragged.
  • The Hex textbox isn’t editable

 

 

Cool Menu

From the sample app:

image

 

Here’s the CHM file doc on this control:

image

So we’ve got Items, MaxItemHeight, MaxItemWidth, MenuIndexChanged, MenuItemClicked  & MenuItemClickEffect.

 

Let’s build a quick cool menu with some items.
I’ll use Dobby the penguin from Jose Farajdo’s blog - http://advertboy.wordpress.com/blendcandy/.

   <SilverlightContrib:CoolMenu Height="200">

            <SilverlightContrib:CoolMenu.Items>

                <SilverlightContrib:CoolMenuItemCollection>

                    <SilverlightContrib:CoolMenuItem>

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem>

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem>

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem>

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem>

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem>

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                </SilverlightContrib:CoolMenuItemCollection>

            </SilverlightContrib:CoolMenu.Items>

        </SilverlightContrib:CoolMenu>

I’m not crazy about this syntax.

First, I have to specify I’m using the Items collectiom, than the specific collection CollMenuItemCollection, than a CoolMenuItem, than Content and finally I can specify the actual Items. Why not support a much simpler syntax?

        <SilverlightContrib:CoolMenu Height="200">

            <SL_Contrib:PenguinControl />

            <SL_Contrib:PenguinControl />

            <SL_Contrib:PenguinControl />

            <SL_Contrib:PenguinControl />

            <SL_Contrib:PenguinControl />

        </SilverlightContrib:CoolMenu>

 

Anyway, let’s run our app with the extended syntax:

image

When we mouse over one of the items:

image

image

This menu is pretty cool.

 

Oh, this is cool: When I click Dobby he drops down and up in a nice elastic bounce motion.

image

image

image

image

Pretty cool.

 

OK, Now I’d like to grab a click on one of the menu items.
We’ll name the menu and add a Text property to the MenuItem.

        <SilverlightContrib:CoolMenu Height="200" x:Name="menu">

            <SilverlightContrib:CoolMenu.Items>

                <SilverlightContrib:CoolMenuItemCollection>

                    <SilverlightContrib:CoolMenuItem Text="Penguin #1">

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem Text="Penguin #2">

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem Text="Penguin #3">

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem Text="Penguin #4">

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem Text="Penguin #5">

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                    <SilverlightContrib:CoolMenuItem Text="Penguin #6">

                        <SilverlightContrib:CoolMenuItem.Content>

                            <SL_Contrib:PenguinControl />

                        </SilverlightContrib:CoolMenuItem.Content>

                    </SilverlightContrib:CoolMenuItem>

                </SilverlightContrib:CoolMenuItemCollection>

            </SilverlightContrib:CoolMenu.Items>

        </SilverlightContrib:CoolMenu>

 

    public partial class CoolMenuPage : UserControl

    {

        public CoolMenuPage()

        {

            InitializeComponent();

            menu.MenuItemClicked += new SilverlightContrib.Controls.MenuIndexChangedHandler(menu_MenuItemClicked);

        }

 

        void menu_MenuItemClicked(object sender, SilverlightContrib.Controls.SelectedMenuItemArgs e)

        {

            txt.Text = e.Item.Text;

        }

    }

 

image

image

 

Nice.

 

Pros:

  1. Pretty cool all and all. The resizing effect, the nice elastic bounce on click and how the rest of the items move. All of these create a solid User eXprience.

Cons:

  • The menu only ships with 2 types of effects “Bounce” and “None”. There’s no extensible mechanisms to add your own effect. Not even through VSM. 
  • The menu should inherit from ItemsControl, which it doesn’t. I can’t use any Item templating goodness with this control. I’d like to be able to run this code:

menu.ItemSource = new List<Person>()

           {

               new Person(Name = "Justin", Picture = "Awesomeness.jpg"),

               new Person(Name = "RJ", Picture = "YaImADutch.jpg"),

               new Person(Name = "Dobby", Picture = "Penguin.jpg"),

           };

        <SilverlightContrib:CoolMenu>

            <SilverlightContrib:CoolMenu.ItemTemplate>

                <DataTemplate>

                    <StackPanel>

                        <Image Source="{Binding Picture}" />

                        <TextBlock Text="{Binding Name}" />

                    </StackPanel>

                </DataTemplate>

            </SilverlightContrib:CoolMenu.ItemTemplate>

        </SilverlightContrib:CoolMenu>

 

 

 

Tweening

From Wikipedia:

“Inbetweening or tweening is the process of generating intermediate frames between two images to give the appearance that the first image evolves smoothly into the second image. Inbetweens are the drawings between the keyframes which help to create the illusion of motion. Inbetweening is a key process in all types of animation, including computer animation.” – copied from http://en.wikipedia.org/wiki/Tweening 

Basically, Tweening is creating cool effects :)

Let’s see a basic example of this.

Here’s a basketball I draw in a few seconds in Blend:

image

(Yes, It’s a Basketball. Prove that it isn’t.)

Now, I’d like for it to bounce down and up and down again in a realistic fashion.

image

 

In order to do that, We’ll add a storyboard in Blend.

image

 

At 0.0 we want the basketball to be at the initial position.

image

At 0.5 seconds we want it at the bottom.

image

At 0.7 seconds we want it to back up a bit.

image

And down again in 0.8 seconds:

image

And on load we’ll start the stortboard:

        void SilverlightControl1_Loaded(object sender, RoutedEventArgs e)

        {

            Resources["Storyboard1"].As<Storyboard>().Begin();

        }

 

 

Than once we run the page we’ll see the full animation.

However, we might not want to specify each possible frame to build realistic effects.
It’s hard, and it’s a very hard task.

In comes the Tweening library.
First, we’ll delete all keyframes besides the last one.

image

Than, back in Visual studio we’ll have a look at that last keyframe.

        <Storyboard x:Name="Storyboard1">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="canvas" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">

                <SplineDoubleKeyFrame KeyTime="00:00:00.8000000" Value="186"/>

            </DoubleAnimationUsingKeyFrames>

        </Storyboard>

We’ll start by deleting even that last animation and copying it’s Keyframe time to the Duration.

        <Storyboard x:Name="Storyboard1">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"

                                          Duration="00:00:00.8000000"

                                          Storyboard.TargetName="canvas"

                                          Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" />

        </Storyboard>

Next, We’ll add some Tweening attached properties.

image

Now, let’s set the initial value, the target value, the number of frames we’d like generated for us and the Transition type. .

image image image

And here’s our final storyboard XAML:

<Storyboard x:Name="Storyboard1">

    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"

                                  Duration="00:00:00.8000000"

                                  Storyboard.TargetName="canvas"

                                  Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)"

                                  Tweener:Tween.From="0"

                                  Tweener:Tween.To="186"

                                  Tweener:Tween.Fps="20"

                                  Tweener:Tween.TransitionType="EaseInOutBounce"

                                  />

</Storyboard>

 

And once we run our app we can see the ball falls down, bounces up a bit and falls back down.

 

Pro:

  1. Tweening is a well established concept in the designer audience and a very productive way of creating complex animations quickly.

Con:

  • No blend support.

 

 

Clipboard support

At times you might want to have Silverlight access directly into your clipboard. Which isn’t natively supported in Silverlight.

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

    <TextBox x:Name="tbx" />

    <Button Click="Copy_Click" Content="Copy TextBox to clipboard" />

    <Button Click="Paste_Click" Content="Paste clipboard to TextBox" />

    <Button Click="Clear_Click" Content="Clear clipboard" />

</StackPanel>

 

Here’s how this page looks like when we run it.

image

 

We’d like the copy button to copy the Text from the TextBox to the clipboard.

First, we’ll create a property that will use lazy initialization to Initialize a ClipboardHelper class.

private ClipboardHelper _clipboard = null;

ClipboardHelper Clipboard

{

    get

    {

        try

        {

            if (_clipboard == null)

                _clipboard = new ClipboardHelper();

        }

        catch (InvalidOperationException)

        {

            MessageBox.Show("Current browser isn't supported for clip board opearations.");

        }

        return _clipboard;

    }

}

This class has resource implications and browser support implications, so it’s best to cache it once initialized.

 

Now, once the Copy button is clicked we’d like to copy the contents of the TextBox into the Clipboard.

        private void Copy_Click(object sender, RoutedEventArgs e)

        {

            if (Clipboard != null)

                Clipboard.SetData(tbx.Text);

        }

Let’s run this application and put some text into the TextBox:

image

 

Once we click the button the user will be prompted to allow the browser app to access the clipboard:

image

The user must click “Allow Access”.

 

Now let’s paste this outside our browser:

image

 

So we can use the Clipboard helper from SIlverlight contrib to cross through browsers boundaries.

 

Now, let’s implement all buttons.

        private void Copy_Click(object sender, RoutedEventArgs e)

        {

            if (Clipboard != null)

                Clipboard.SetData(tbx.Text);

        }

 

        private void Paste_Click(object sender, RoutedEventArgs e)

        {

            if (Clipboard != null && !string.IsNullOrEmpty(Clipboard.GetData()))

                tbx.Text = Clipboard.GetData();

        }

 

        private void Clear_Click(object sender, RoutedEventArgs e)

        {

            if (Clipboard != null)

                Clipboard.ClearData();

        }

And once we run our application we see that we can copy information from outside the browser inside our Silverlight Application.

image

image

 

And we can clear the clipboard and paste again to see it’s been emptied out.

image

 

Pros:

  1. Clipboard support is something that can make or break certain apps.
  2. This is an excellent API for something that is basically a huge managed wrapper around Javascript. Having a Dispose method on the ClipboardHelper shows the Contrib team really did a good job here.
  3. This could enable a range of scenarios (copying whole files from outside the browser?)

Con:

  • The current implementation is not supported in FireFox.

image

 

 

Sum up

The Silverlight Contrib is a top notch open source project with some excellent controls, utilities and helpers you should definitely take a look at.

Go get it at http://codeplex.com/SilverlightContrib.

 

 

-- Justin Angel 

Microsoft Silverlight Toolkit Program Manager

Published Tuesday, December 30, 2008 7:23 PM by JustinAngel

Comments

# Tour around Silverlight Contrib - Justin myJustin = new Microsoft.Silverlight.Justin();

Pingback from  Tour around Silverlight Contrib - Justin myJustin = new Microsoft.Silverlight.Justin();

# Silverlight Cream for December 30, 2008 - 2 -- #472

In this issue: Guy Ellis, Jonathan van de Veen, Jesse Liberty, Beatriz Stollnitz, Justin Angel, Manish

Wednesday, December 31, 2008 2:10 AM by Community Blogs

# re: Tour around Silverlight Contrib

Hi, CoolMenu is outstanding, I have just build really nice menu in 5 minutes - find out at my blog.

Thanks for post

HJ

Wednesday, December 31, 2008 7:34 AM by kalimevole

# Dew Drop - January 1, 2009 | Alvin Ashcraft's Morning Dew

Pingback from  Dew Drop - January 1, 2009 | Alvin Ashcraft's Morning Dew

Thursday, January 01, 2009 4:13 PM by Dew Drop - January 1, 2009 | Alvin Ashcraft's Morning Dew

# Weekly Web Nuggets #45

Pick of the week: Thinking Only of the Junior Developer General Internals Viewer for SQL Server : A neat tool for visualizing the SQL Server storage engine. Introducing the New Task Type : Daniel Moth shows how the new Task type in .NET 4 can make parallel

Monday, January 05, 2009 1:12 PM by Code Monkey Labs

# re: Tour around Silverlight Contrib

Justin, thx for support my blog!

You posts are interesting as well.

I got an new idea from your blog. I think I am going to illustrate all the special features inside the Silverlight Toolkit!

Saturday, January 10, 2009 12:32 AM by shinedraw

# Refactoring the CoolMenu Control

Refactoring the CoolMenu Control

Sunday, January 18, 2009 10:50 PM by Page Brooks

# Weekly Web Nuggets #45

Pick of the week: Thinking Only of the Junior Developer General Internals Viewer for SQL Server : A neat tool for visualizing the SQL Server storage engine. Introducing the New Task Type : Daniel Moth shows how the new Task type in .NET 4 can make parallel

Sunday, February 22, 2009 10:30 PM by Code Monkey Labs

# re: Tour around Silverlight Contrib

Do these samples work at SL Contribe 1.0? I would like to do small series about some controls of SL Contrib and this is the only document I can use like source.

Thank you a lot for answer.

Kali

Thursday, March 05, 2009 6:30 PM by kalimevole

# re: Tour around Silverlight Contrib

Hi Justin,

Thanks for all your samples. I have been talk you could know when the Silverlight 3 Toolkit in French would be available ? At the moment : it is available only in english and japanese, and we are looking forward to develop business application with it !!

Thanks

Wednesday, April 22, 2009 1:52 AM by soonia