(14 votes)

Creating a Silverlight Custom Control - The Basics

6 comments   /   posted by   Emil Stoychev on Jun 16, 2008

Introduction

This articles focuses on the process of creating a Custom Control in Silverlight 2. It describes the basics of what you need to build a styleable control with custom logic that can be used in Silverlight applications. The article shows a sample(part) of implementing a LinkLabel control that recognizes URIs in a given text and displays them as links instead of as plain text.

Overview

The control model in Silverlight 2 offers creating UserControls and Custom Controls. UserControls enable encapsulation of a specific logic. They are used in scenarios where you want to reuse XAML and/or logic in multiple places or build a sophisticated page with smaller chunks(the UserControls). However, in other scenarios you may need a custom logic to be built in the control and this control to allow designers customize easily its look. You need a way to modify the control visuals without having to modify the control logic. This is where the Custom Controls comes in handy. In Silverlight they derive from the Control class and specify a default style for the way they will look like.

To get started create a Silverlight Class Library project in VisualStudio 2008. This will generate just a single .cs file. Lets take a sample implementation of a LinkLabel control.

   1: public class LinkLabel : Control
   2: {
   3: ...
   4: }

Ok, the first step is to define a default look for this control. A file called generic.xaml contains the UI of your custom controls. Add a new item of type XML File in your project and name it generic.xaml. By default when you add a new file the Build Action is set to Silverlight page. But the platform look for the generic.xaml as a Resource file. Therefore you need to change the default behavior:

  1. Open the Properties window of the file.
  2. Change the Build Action to Resource.
  3. Clear the Custom Tool value.

generic.xaml.build.action 

In the generic.xaml add a ResourceDictionary element where you will put all the resources.

   1: <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   3: ...
   4: </ResourceDictionary>

The next step is to add the default style for the control. Start by including the XML namespace of the assembly.

   1: <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   3: xmlns:local="clr-namespace:CompletIT.Windows.Controls;assembly=LinkLabel">
   4: 
   5:     <!-- Default style for CompletIT.Windows.Controls.LinkLabel -->
   6:     <Style TargetType="local:LinkLabel">
   7:         <Setter Property="Template">
   8:             <Setter.Value>
   9:                 <ControlTemplate TargetType="local:LinkLabel">
  10:                     <StackPanel x:Name="LayoutRoot">
  11:                         <ContentPresenter />
  12:                     </StackPanel>
  13:                 </ControlTemplate>
  14:             </Setter.Value>
  15:         </Setter>
  16:     </Style>
  17: </ResourceDictionary>
 


In this code snippet you see a Style element just like the one you might have already used in your Silverlight applications. You may also notice that there is no x:Key attribute - you don't need it because when the platform looks for the default style of the control it just examines the TargetType. To specify the control's look set the Template property and add a ControlTemplate. This is where you can define the full appearance of the control.

With the release of the VisualStateManager in Beta 2 it is important to point that this style is also the place where you can define the state parts of your control. This is not the main focus of this article so I won't get deep in it. For more information on this topic you can read Parts & States Model with VisualStateManager and watch Creating Rich, Dynamic User Interfaces with Silverlight 2 by Karen Corby.

Ok, enough of XAML. Lets see what's needed in the code.

Start with creating a constructor and set the FrameworkElement.DefaultStyleKey - type that should be used to look up the built-in style - to the Type of the control.

   1: public LinkLabel()
   2:     : base()
   3: {
   4:     DefaultStyleKey = typeof( LinkLabel );
   5: }

Then, define all the custom properties of the control. Most of the properties in the framework are of DependencyProperty type. If you want a particular property of your control to be template-bindable, data-bindable or styleable,  you need to define it as a DependencyProperty. For the LinkLabel control lets just add a Text property.

   1: public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
   2:             "Text",
   3:             typeof( string ),
   4:             typeof( LinkLabel ),
   5:             new PropertyMetadata( new PropertyChangedCallback( OnTextChanged ) ) );
   6: 
   7: public string Text
   8: {
   9:     get
  10:     {
  11:         return ( string )this.GetValue( TextProperty );
  12:     }
  13: 
  14:     set
  15:     {
  16:         base.SetValue( TextProperty, value );
  17:     }
  18: }

As you can see on line 5 a new PropertyChangedCallback is added that will be called when the text is changed. This is not needed for all controls. We will walk through the implementation of the OnTextChanged method in a second. Do the same for all properties your control needs.

One last step before proceeding to the control logic code. The StackPanel we use for a "built-in" style in the generic.xaml is still not accessible from the code file. To assign it to a member variable create a private field of type StackPanel and override the OnApplyTemplate method like this:

   1: public override void OnApplyTemplate()
   2: {
   3:     this.layoutRoot = this.GetTemplateChild( "LayoutRoot" ) as StackPanel;
   4:     Debug.Assert( this.layoutRoot != null, "LayoutRoot is null" );
   5: 
   6:     base.OnApplyTemplate();
   7: }

As you see in the above code we call this.GetTemplateChild(childName) to retrieve the element from the visual tree.

That's it. From there on you should write the custom logic needed by your control to act as you want. For our LinkLabel sample we need to process the entered text by replacing all URIs with links. To achieve this we need to define a new method (ProcessText()) that should be called (1) from the OnApplyTemplate event and (2) from the OnTextChanged event. I'll skip the implementation of the ProcessText method here as I'll blog about the full implementation of the LinkLabel control later this week and will provide the source code and a sample usage.

   1: private static void OnTextChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
   2: {
   3:     LinkLabel linkLabel = d as LinkLabel;
   4:     Debug.Assert( linkLabel != null, "LaytouRoot is null" );
   5: 
   6:     linkLabel.ProcessText();
   7: }

Conclusion

Building a Custom Control in Silverlight can be tricky sometimes, but that really depends on the complexity the control requires. Silverlight really gives the freedom to create whatever your imagination can born and push it to the highest level. You are able to build beautiful controls that can be easily customized by designers on their own. You are sure that the designer won't brake your logic while making the fascinate look of the control. With the new VisualStateManager and the "Parts and States Model" you can easily define complex UI while keeping the designer's ability to style it. This is another quite a big and interesting topic that I'll try to cover in future posts.

Stay tuned to see the LinkLabel control. I'll provide a link in this article too.

Update
Check out the LinkLabel control here.

References

Styling and Templating Overview on MSDN
Creating a Templatable Control on MSDN
Creating Rich, Dynamic User Interfaces with Silverlight 2 by Karen Corby
Parts & States Model with VisualStateManager by Karen Corby



Comments

Comments RSS RSS

RE: Creating a Silverlight Custom Control - The Basics  

posted by Sad on Jun 16, 2008 18:12

So if Silverlight is so cool in regards to creating LinkButtons (or LinkLabels), why not re-create this website with XAML instead of HTML? Ohh yeah, that's right; because it's ActiveX technology, instable doesn't get indexed by search engines which means it won't attract visitors from Google and generally not suitable for creating web-stuff...

Market Silverlight as what it is and not what you're hoping it to be. Flash 2.0, JavaApplets 2.0 or even ActiveX 2.0. Then again, if you did then developers won't really bother to invest in it then I guess ;)

Though I think this will be its curse anyway...

You guys are big, but you're NOT big enough (at least not now) to combat the _ENTIRE_ web alone. How about building on Open Standards instead of continuing de-commoditizing Open Web standards and protocols (ref; Halloween)

Maybe you'd get to at least fade out with PRIDE and people remembering you for what you did which actually was GOOD which was putting a computer in front of (almost) every human on the planet instead of what you're risking now which is that history will remember you as the guys who consistantly refused to fade away without trying to drag the entire world with them...

Sad... :(

Every single waken analyst with more than two intact braincells knows that Silverlight will _NOT_ prevail, you guys really should get some better advice... :(

You guys have so much power and so much money, imagine how much GOOD that could do in regards to innovation. Instead you're consistantly choosing to harm innovation... :(

And you won't even succeed...

At the end of the day it'll all end up as money being poured into a bottomless hole...

Sad! :(


RE: Creating a Silverlight Custom Control - The Basics  

posted by Dejan on Jun 17, 2008 00:42

To the author of the article: Thank you for a very informative tutorial.

To the writer of the comment above: This was a technical article. Your comments have completely missed the point.  Nobody really cares about your lamenting.


RE: Creating a Silverlight Custom Control - The Basics  

posted by Chris on Jul 04, 2008 00:36

Thanks for the article! it's great.

To Sad,

This is not a good place for you to whine around. You should stick with your open standards may be.


RE: Creating a Silverlight Custom Control - The Basics  

posted by Richard Fencel on Jul 22, 2008 17:15

Unbelievably simple great "hello world" article.  Saved me tons of head scratching and therapy expense.


RE: Creating a Silverlight Custom Control - The Basics  

posted by Geoffrey Swenson on Jul 31, 2008 16:08

Yes very helpful. Any tips of taking this further?


RE: Creating a Silverlight Custom Control - The Basics  

posted by emil on Aug 03, 2008 22:52

Add Comment