(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Creating a Silverlight Custom Control - The Basics

(45 votes)
Emil Stoychev
>
Emil Stoychev
Joined Oct 15, 2007
Articles:   23
Comments:   98
More Articles
23 comments   /   posted on Jun 16, 2008
Categories:   Controls
Tweet This!

This article is compatible with the latest version of Silverlight.


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 Visual Studio. This will generate just a single .cs file. Lets take a sample implementation of a LinkLabel control.

 public class LinkLabel : Control
 {
 ...
 }

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. It should be placed in a "themes" directory inside your project. Add a new item of type XML File in your project in the "themes" directory 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.

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

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

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:local="clr-namespace:CompletIT.Windows.Controls;assembly=LinkLabel">
 
     <!-- Default style for CompletIT.Windows.Controls.LinkLabel -->
     <Style TargetType="local:LinkLabel">
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="local:LinkLabel">
                      <StackPanel x:Name="LayoutRoot">
                          <ContentPresenter   />
                      </StackPanel>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
      </Style>
 </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.

 public LinkLabel()
     : base()
 {
     DefaultStyleKey = typeof( LinkLabel );
 }

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.

 public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
             "Text",
             typeof( string ),
             typeof( LinkLabel ),
             new PropertyMetadata( new PropertyChangedCallback( OnTextChanged ) ) );
 
 public string Text
 {
     get
      {
          return ( string )this.GetValue( TextProperty );
      }
  
      set
      {
          base.SetValue( TextProperty, value );
      }
 }

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:

 public override void OnApplyTemplate()
 {
     this.layoutRoot = this.GetTemplateChild( "LayoutRoot" ) as StackPanel;
     Debug.Assert( this.layoutRoot != null, "LayoutRoot is null" );
 
     base.OnApplyTemplate();
 }

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.

 private static void OnTextChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
 {
     LinkLabel linkLabel = d as LinkLabel;
     Debug.Assert( linkLabel != null, "LaytouRoot is null" );
 
     linkLabel.ProcessText();
 }

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


Subscribe

Comments

  • -_-

    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?

  • emil

    RE: Creating a Silverlight Custom Control - The Basics


    posted by emil on Aug 03, 2008 22:52
  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Fleckney on Oct 16, 2008 01:32

    Thanks for getting me started on SilverLight Custom Controls, it is a great article. I would like to thank Sad for confirming that devotees of Open Source are short sighted bigots.   

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Having difficulty on Oct 22, 2008 08:45

    Hi, I'm getting a compile error on this line in the customer class:

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(

    It says it is looking for a delegate.  Am I missing something or did I forget a step?  Thanks!

  • emil

    RE: Creating a Silverlight Custom Control - The Basics


    posted by emil on Oct 23, 2008 03:32

    Hi, I'm not sure what exactly you are trying to do.

    1: public static readonly DependencyProperty TextProperty = DependencyProperty.Register(

       2:             "Text",
       3:             typeof( string ),
       4:             typeof( LinkLabel ),
       5:             new PropertyMetadata( new PropertyChangedCallback( OnTextChanged ) ) );

    This is the way you register the DependencyProperty Text. It is correct and should not give you any kind of error during compilation.

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Chandima on Nov 05, 2008 13:00

    This article is fantastic. I was searching internet for days and looking for such an article. I even read Silverlight Tutorials in Microsoft website but they were too complicated and I didn't understand what they were saying. This article is written to the point and thank you so much for making it easy.

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Uchimata on Jan 06, 2009 10:58

    I can't say thanks enough for you Man! Thank you so much! I've stuck into the generic.xaml problem for a couple of everlasting days. I've redone everything from the scratch several times, but I've not realized till now (thanks for your article) that a "/themes/generic.xaml" structure is a requirement, and I always created my own conventions. What a silly I am. So thank you Emil for this clear, unambiguous and great article!

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by freeze on Feb 24, 2009 17:44

    great article, thanks.

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by voiddog on Mar 23, 2009 12:38
    Very helpful. Cheers.
  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by rollo on Mar 31, 2009 17:45
    I have been unable to get this to work... Has anyone else run into problems? I have tried added the .dll as a resource to blend 2. When I use the control it throws an error.

    While trying to build the LinkLabel in VS2008 I get errors about WrapPanel?!?! Saying it is a namespace but is used like a type...

    I am new to silverlight and my coding skills are rusty so need a little extra hand holding here.
  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Exorsus on Apr 24, 2009 14:49
    Exceptionaly excelent explanation of this topic !!! five stars in my opinion .... thank you :-)
  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Anand on Aug 04, 2009 00:17

    Hi,

     I am using Silverlight 2 env for my development. I have created a silverlight control library to create some custom controls which i would be using in my application. I was able to create the project sucessfully add a custom control and integrate with another appication to consume the control, that too works good. Now I try to add another custom control to the same project I did the following steps.

    1. Created a cs file for the second custom control.

    2. in generic.xaml I added another style tag to the rescource dictionary for the new custom control.

    3. did all the coding part in cs file required and complied the app.

    4. referenced the app to another project to consume it. Now i see the custom control 1 and as well the custom control 2 have runtime error(its just the AG_E_UNKOWN_Error).

    But without the style block for the second control in the resource dictionary my custom control 1 works fine if i add the style for the custom control 2. It cause the runtime error.

    Could any pls correct me if am not using resourcedictionary properly or is there anything else Iam missing to have a library containing more than one custom control in it.

    <ResourceDictionary
    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
    xmlns
    :sys="clr-namespace:System.Windows;assembly=System.Windows"
    xmlns:xyzCtl="clr-namespace:xyzCtlLibrary"
    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows" > 
     <Style TargetType="xyzCtl:Expander">
     
    <Setter Property="BorderThickness" Value="1"/>
      <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
      <Setter Property="VerticalContentAlignment" Value="Stretch"/>
      <Setter Property="Template">
       <Setter.Value>
        <ControlTemplate TargetType="xyzCtl:Expander">
        <!--  Control Template XAML--!>
        </ControlTemplate>
       </Setter.Value>
      </Setter>
     </Style>
     <Style TargetType="xyzCtlLibrary:Widgets">
      <Setter Property="Template">
       <Setter.Value>
        <ControlTemplate TargetType="xyzCtlLibrary:Widgets">
        <!--  Control Template Xaml-->
        </ControlTemplate>
       </Setter.Value>
     
    </Setter>
     </Style>
    </ResourceDictionary>

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by C# Student on Mar 19, 2010 22:41
    I got the same problem as Anand, further investigation of what causes the error led me to find that the Template is not set for my control. Any help would be welcomed
  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Brandon on Jun 21, 2010 02:38
    I am trying to design a basic control, basically a content window with a title.
    On par with your example I would need a dependancy property "Title". How do I make it so that the actual label inside the control is set/bound to the value of "Title"? Since the label is inside of a template I can't actually reference it and since the DataContext of the control is bound to something else. I don't see you doing anything with your dependancy property above, I am confused.
  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by tootee on Jul 29, 2010 19:44
    Actually Silverlight has great potential in some cases and applications.
  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Concerned on Feb 05, 2011 04:50

    Sad:

    When you think your knowledge is so much greater and your insight so much keener than thousands upon thousands of highly intelligent and successful professionals (who far eclipse me) and you're not a great leader, you gotta ask yourself why. Delusions of grandeur? Crippling neuroses? Whatever, if you look at what your comments at all objectively you'll have to agree you need help. If you're as smart as you think you are, you should have better things to do than being a troll.

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by Happy on Feb 24, 2011 22:16

    Sad:

    It is 2011, and Silverlight is the WAY to develop a true advanced bussenis web applications.

    Happy?!

  • -_-

    RE: Creating a Silverlight Custom Control - The Basics


    posted by ovidiuc@gmail.com on Apr 06, 2011 21:11

    DefaultStyleKey is not available in Silverlight... your article is either wrong or outdated.

  • Selva

    Re: Creating a Silverlight Custom Control - The Basics


    posted by Selva on Sep 29, 2011 12:35

    Sad :

    You had the foresight to tell the fate of silverlight. Microsoft's strategy has changed, BUILD ??.  The world is moving towards Plug-in free model and Silverlight will become history. XAML is one good innovation came out of these technologies (WPF/SL), that we can't deny.

Add Comment

Login to comment:
  *      *