In part one, a buttonlike control was created. It worked like a button, or at least a little. It was a square with a descriptive text and a brand new Click event. Unfortunately that doesn't really make it feel like a button. There is more to a button, especially in Silverlight and WPF. First off, a button normally gives some visual feedback to the user, confirming that it is pressed or that the button is hovering over it. That visual feedback is something that you find in most button implementation, wether it is in Windows Forms, HTML or WPF. The thing that is special with buttons in WPF and Silverlight is that the content of the button - in this case the descriptive text - can be anything. And I mean ANYTHING. It could be a Grid with several controls inside. Not that I would recommend doing some of the things that you CAN do, but it is possible. So in this part of the tutorial, the button will get visual feedback and support for complex content.

Lets start off with the support to add anything as content in the control. To add this support is actually pretty simple. First off the TextBlock, that is in the template now, must be removed. Or actually not so much removed as replaced, replaced with a ContentPresenter. The the inheritance of the control has to be changed from Control to ContentControl. That's all there is to it. Oh..yeah...and remember to remove the Text property as well, since it isn't being used anymore it shouldn't be in there...

<TextBlock Text="{TemplateBinding Text}" 
           HorizontalAlignment="Center" 
           VerticalAlignment="Center"
           Foreground="{TemplateBinding Foreground}"/>

Is replaced with

<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />

And the inheritance of the control is changed to

public class MyButton : ContentControl
{
    ...
}

So...this change now forces a change in the "test button". Change the "test button" from using the Text property to use the newly added Content property instead. It could look something like the following

<btn:MyButton Width="100" Height="50" Background="Yellow" Foreground="White" Click="MyButton_Click">
    <btn:MyButton.Content>
        <TextBlock Text="Hello Content" />
    </btn:MyButton.Content>
</btn:MyButton>

The eventhandler of course has to be changed as well, since it works with the Text property. To have the same effect, the new TextBlock has to be named and then modified from the handler

<btn:MyButton Width="100" Height="50" Background="Yellow" Foreground="White" Click="MyButton_Click">
    <btn:MyButton.Content>
        <TextBlock Text="Hello Content" x:Name="ContentText" />
    </btn:MyButton.Content>
</btn:MyButton>
private void MyButton_Click(object sender, MouseEventArgs e)
{
    ContentText.Text = "Hello again";
}

So...now that the content part has been changed, it is time to take care of the visual changes. In the Silverlight 2 beta, all visual changes where based on animations with specific names that were then called from the controls code. The idea is the same today, but it is a little less "fragile". Animations are still responsible for the visual changes, but they aren't called by name from code anymore. This use of specific named is too "fragile". Instead a new control was introduced, the VisualStateManager. The VisualStateManager is responsible for setting states. A state is a specific visual state. So the different states are defined in the VSM and then the code uses the VSM to set. How does this make it less fragile? Well, this will be shown in a little while.

The cool thing about the VSM is that it supports states and state groups. Only one state within a state group can be set at once. But multiple state groups can have states set. So in the MyButton control, there will be only one state group. But if you have a look at for example the Button control it uses two groups, "FocusStates" and "CommonStates". But as said before, the MyButton control will only have a single state group called "CommonStates". Inside that group, it will have 3 states - "Normal", "MouseOver" and "Pressed". These states might not seem logical to everyone, but the cool thing is that every developer can choose the names of the groups and states by themselves. So in this case...it is like this...comprende...

So...to start using the VSM it has to be added to our xaml. This isn't really hard, but it is in a separate assembly and namespace so we need a new xml namespace in the xaml.

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyButton"
    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
    >
...

Next it is time to add the state groups and states. This can be done from 2 directions. Either setting them in code first and them create the xaml, or starting from xaml and then doing the code. It doesn't really matter as long as the different groups and states are already set on paper somewhere... In this case, it will start in the xaml. The VSM is added inside the root Grid like this

<Grid Background="{TemplateBinding Background}">
    <vsm:VisualStateManager.VisualStateGroups>
        <vsm:VisualStateGroup x:Name="CommonStates">
            <vsm:VisualState x:Name="Normal" />
            <vsm:VisualState x:Name="MouseOver" />
            <vsm:VisualState x:Name="Pressed" />
            </vsm:VisualState>
        </vsm:VisualStateGroup>
    </vsm:VisualStateManager.VisualStateGroups>
    ...
</Grid>

Now that all the group and all the states are in there, it is time to add the actual visual changes. This is done by adding animations inside the VisualState elements. So select the states that should be handled and add a Storyboard inside that VisualState. In this case the Normal state will be left empty, that will make it return to the original layout when that state is set. So to handle the MouseOver and Pressed states, the Xaml is changed like this

<vsm:VisualStateManager.VisualStateGroups>
    <vsm:VisualStateGroup x:Name="CommonStates">
        <vsm:VisualState x:Name="Normal" />
        <vsm:VisualState x:Name="MouseOver">
            <Storyboard>
                <ColorAnimation Storyboard.TargetName="BackgroundBrush" 
                    Storyboard.TargetProperty="Color" To="Red" />
                <DoubleAnimation Storyboard.TargetName="BackgroundBrush" 
                    Storyboard.TargetProperty="Opacity" To=".5" />
            </Storyboard>
        </vsm:VisualState>
        <vsm:VisualState x:Name="Pressed">
            <Storyboard>
                <ColorAnimation Storyboard.TargetName="BackgroundBrush" 
                    Storyboard.TargetProperty="Color" To="DarkRed" />
                <DoubleAnimation Storyboard.TargetName="BackgroundBrush" 
                    Storyboard.TargetProperty="Opacity" To=".5" />
            </Storyboard>
        </vsm:VisualState>
    </vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>

That gives the button some seriously uggly effects, but it will at least make some visual changes... The only problem now, is that the time it takes for the animation is too slow. To counter this, it is possible to add a VisualTransitions telling the VSM how much time to spend on each animation. The Transitions property is set like this

<vsm:VisualStateManager.VisualStateGroups>
    <vsm:VisualStateGroup x:Name="CommonStates">
        <vsm:VisualStateGroup.Transitions>
            <vsm:VisualTransition To="Normal" GeneratedDuration="0:0:0.2"/>
            <vsm:VisualTransition To="MouseOver" GeneratedDuration="0:0:0.2"/>
            <vsm:VisualTransition To="Pressed" GeneratedDuration="0:0:0.2"/>
        </vsm:VisualStateGroup.Transitions>
        ...
</vsm:VisualStateManager.VisualStateGroups>

That is all the Xaml needed. Now it is time to start setting the states from code. The first change that is needed is to handle one more event. The event in question is the MouseEnter event. That changes the constructor to look like the following

public MyButton()
{
    DefaultStyleKey = typeof(MyButton);
    this.MouseEnter += new MouseEventHandler(MyButton_MouseEnter);
    this.MouseLeave += new MouseEventHandler(MyButton_MouseLeave);
    this.MouseLeftButtonDown += new MouseButtonEventHandler(MyButton_MouseLeftButtonDown);
    this.MouseLeftButtonUp += new MouseButtonEventHandler(MyButton_MouseLeftButtonUp);
}

The handler is all emtpy for now. It will only be used for the state handling. Now...the next part is to start handling the states. To set a specific state, all that needs to be done is to call VisualStateManager.GoToState(). It takes three parameters. First the object to set the state on, then the name of the state and finally if a transition should be used. THis is kind of cool, because it makes it possible to set the states of other objects and not only your own object...be careful though... So...lets set the state in the different handlers. No...lets not do that. What should be done is to create a method that handles the actual setting of the state. That way all state setting is handled in one place. To support this method, there needs to be some way of telling it what to set. How about sending in the state to the method. No...then you are back to the distributed handling of states... Add a couple of state bools in the class. Then the handlers can set the state bool that is relevant and then just call a state setting method and let it figure out what to do. Something like this

bool _mouseOver = false;
bool _mousePressed = false;

private void SetState()
{
    if (_mousePressed)
        VisualStateManager.GoToState(this, "Pressed", true);
    else if (_mouseOver)
        VisualStateManager.GoToState(this, "MouseOver", true);
    else
        VisualStateManager.GoToState(this, "Normal", true);
}

After adding this simple method it is possible to implement the handlers. All they have to do is set the bool values and then call SetState(). In this control this seems like "a lot" of extra work, but in a control with several state groups and and more states, it makes it a lot simpler to handle different state combinations. The handlers should look something like this

void MyButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    _mousePressed = true;
    SetState();
}
void MyButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    if (_mousePressed)
    {
        OnClick(e);
    }
    _mousePressed = false;
    SetState();
}
void MyButton_MouseEnter(object sender, MouseEventArgs e)
{
    _mouseOver = true;
    SetState();
}
void MyButton_MouseLeave(object sender, MouseEventArgs e)
{
    _mousePressed = false;
    _mouseOver = false;
    SetState();
}

That's it! Well...more or less. I was talking about how fragile the old state handling system was with specifically named animations...this doesn't seem a lot better. Well, so far it isn't. The only difference is that we get some state help from the VSM with groups and things. But it is still state names with strings that we have to figure out if we change the template. The solution to this is attributes. There are two attributes that help us when it comes to templating through tools like Expression Blend. TemplateVisualState and TemplatePart...by setting these attributes on our control, tools like Blend can automatically figure out what parts and states are available and add tooling support for it. The TemplateVisualState has 2 properties, GroupName and Name. They are both strings and define what groups and what states the controls code use. The TemplatePart attribute is a little different. It tells the tool what "parts" it needs in the template and what types they are.

Parts? What? I get states, but what is parts... Well, say that your control expects there to be a button somewhere in the template so that it can handle the user clicking it. Well, if somebody changes the template for the control, they have no idea that there should be that specific button and what it should be named unless they are told. The Slider control is a perfect example. The Slider consists of a bunch of different parts that it needs to work. The attributes for the Slider looks like this

[TemplatePart(Name="VerticalTrackLargeChangeIncreaseRepeatButton", Type=typeof(RepeatButton)), 
TemplatePart(Name="VerticalThumb",Type=typeof(Thumb)), 
TemplatePart(Name="HorizontalTemplate", Type=typeof(FrameworkElement)), 
TemplatePart(Name="HorizontalTrackLargeChangeIncreaseRepeatButton", Type=typeof(RepeatButton)), 
TemplatePart(Name="HorizontalTrackLargeChangeDecreaseRepeatButton", Type=typeof(RepeatButton)), 
TemplatePart(Name="HorizontalThumb", Type=typeof(Thumb)), 
TemplatePart(Name="VerticalTemplate", Type=typeof(FrameworkElement)), 
TemplatePart(Name="VerticalTrackLargeChangeDecreaseRepeatButton", Type=typeof(RepeatButton)),
TemplateVisualState(Name="Normal", GroupName="CommonStates"), 
TemplateVisualState(Name="Focused", GroupName="FocusStates"), 
TemplateVisualState(Name="Unfocused", GroupName="FocusStates"),  
TemplateVisualState(Name="MouseOver", GroupName="CommonStates"), 
TemplateVisualState(Name="Disabled", GroupName="CommonStates")]

Thats a lot of states and parts. So how to know what parts to add in you template if there wasn't TemplatePart attributes. The important thing when adding this attribute is to use as broad a type as possible. If you use a Rectangle in the default template, but only use features defined in UIElement, you should define the TemplatePart type to be UIElement. This makes it possible to create the widest variety of templates for the control. Again, the Slider is a perfect example. It defines the HorizontalTemplate as FrameworkElement...that is very early in the inheritance chain for Silverlight, making it possible to be VERY creative with the HorizontalTemplate.

How does a control use the parts it has defined? Well, the MyButton control wasn't complicated enough to use parts, but here is how it should have been done. Since the parts are defined in the template, it isn't possible to code against them straight off. The best way to get hold of the parts is by overriding the OnApplyTemplate() method. This is called as soon as the template is applied to the control, totally ignoring if the template if the default one or one defined by the user. Inside this method it is possible to get hold of named elements, parts, inside the template by calling GetTemplateChild(). This method will of course work outside of this method as well, as long as it is called after the template has been applied. It takes the name of the part as parameter and returns object. Use the "as" operator and beware of the very possible possibility of getting null back, since the template might not define that part. If a part is missing, there is a choice to make. Can the control work without it or should an exception be thrown. Well...it depends on the control... It could look like this

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    FrameworkElement fe = GetTemplateChild("MyPart") as FrameworkElement;
    if (fe != null)
    {
        fe.MouseEnter += ...
    }
    ...
}

Now, there are a couple of tips and convention that some people talk about. First of all, in WPF there is some convention that the name of a part should start with "PART_". In Silverlight this doesn't seem to be considered important. When dissasembling Microsofts own controls, this convention isn't followed... It's up to you...
The next thing would be to make the name of the parts into static fields... Well, that I could sort of agree with and accept. It could look something like this

[TemplatePart(Name=MyButton.MyPartName, Type=typeof(UIElement))]
public class MyButton : ContentControl
{
    public static readonly string MyPartName = "MyPartName";
    ...    
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        FrameworkElement fe = GetTemplateChild(MyButton.MyPartName) as FrameworkElement;
        ..
    }
    ...
}

But once again, that is up to the developer (you). Having it like this makes it less fragile to typing errors.

That concludes my 2 part tutorial about creating custom controls. It is far from exhausting, but should give you enough information to get started building your own controls. Supporting templates makes your controls so much more useful, since the control can be used over and over again with the same functionality, but appearing to be a totally new and good looking control. But since all "built in" Silverlight controls are templatable, make sure you aren't creating unnecessary controls. Try to re-template existing controls instead, since this is less work and less likely to introduce bugs in the system.

By the way, try adding the MyButton control to a page and use Blend to work with the template. By doing this, you will see that Blend automatically picks up the VisualState attribues and add them so that you can create the animations. Just add the control to a page, open the page in Blend and right-click the control and choose "Edit Control Parts (Template) > Create Empty". Even if the new template is empty, it will have the different states available in the States pane.

Thank you for reading and hope you got something good out of it. Don't hesistate to ask questions or add comments about the tutorial!

After having written mhy previous entry about how to style and template controls, I guess it is a good time to have a look at how to create controls that are template- and styleable. (Can you write "template- and styleable"? Looks weird...well...I am swedish so I'm allowed to write less than perfect english) Unfortunately, due to my lack of imagination, I don't have a really cool control to build and show you. So instead I'm going to create a very limited control that will work more or less as a simple button.

To start off, create a Silverlight Application project in Visual Studio 2008. When asked if a separate webproject is needed for debugging, just go with creating one on the fly. For this exercise there isn't really a need to make changes to the hosting page, whichthat means that VS can just as well create the page on the fly. After VS has created the Silverlight Application project, add another project to the solution. But this time. add a Silverlight Class Library. This isn't necessary, but having the control in a separate assembly makes re-useable. (Probably won't re-use it considering what the control does, but it keeps it real...)

For now, just ignore the application project and focus on the library. Start by removing the Class1.cs file and add a new class called MyButton. Yes...MyButton...it sucks I know, but it works... Start off by modifying the inheritance of the class. Change the class so it inherits from Control to start with. This will be changed later, but start like this.

Before moving further, there has to be a layout for the control. This should of course be Xaml. It is possible to create the layour from code, but that removes the possibility of templating the control and because of this the Xaml way is the correct way. Adding a default template to the control is not that hard, but not really obvious. Start by adding a folder called "themes" in the root of the application. Inside the themes folder, add a new Xaml file. This is easiest to do by adding an Xml file and just renaming it. It has to be named "generic.xaml". After the file has been added, some changes to it's build action has to be made. Select the file in the Solution Explorer and take a look at the Properties pane. Now there are aparently at least two settings that work here, but the oficial one is the one I will use. Set the "Build Action" to "Resource" and make sure that the "Custom Tool" part is empty. (The other way is to set the "Build Action" to "Page" and then leave/set the "Custom Tool" to "MSBuild:MarkupCompilePass1". This worked for me, but I wouldn't recommend it)

The content of the "generic.xaml" file has to start off by looking like the following:

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

So if the "generic.xaml" file was started by adding an Xml file, the Xml declaration at the top has to be removed first. Now that the "generic.xaml" has been turned into a resource dictionary, it is possible to add a default template to the MyButton control. As said in the previous post, a template is actually a specific setter inside a style, so the resource dictionary needs a style. But since the style needs to have its TargetType to point at the MyControl control we have to make a small modification to our Xaml. To be able to reference the MyButton control, an xml-namespace pointing towards the correct namespace has to be added. An xml-namespace with a clr-namespace reference is sort of like adding a "using" statemen. After the xml-namespace has been added, it is possible to add the style and point it to the right target type.

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyButton"
    > 
    <Style TargetType="local:MyButton">
    </Style>
</ResourceDictionary>

Next it is time to set the template of the control by adding a setter that sets the "Template" property of the control. It is going to be a very simple template, but it will show the idea.

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyButton"
    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
    > 
    <Style TargetType="local:MyButton">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyButton">
                    <Grid Background="{TemplateBinding Background}">
                        <Rectangle>
                            <Rectangle.Fill>
                                <SolidColorBrush x:Name="BackgroundBrush" Opacity="0" />
                            </Rectangle.Fill>
                        </Rectangle>
                        <TextBlock Text="{TemplateBinding Text}" 
                                   HorizontalAlignment="Center" 
                                   VerticalAlignment="Center"
                                   Foreground="{TemplateBinding Foreground}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style> 
</ResourceDictionary>

The template contains 3 template bindings. A template binding will casue the value of the property with the binding to have it's value set by a property in the control. So the "{TemplateBinding Foreground}" will set the TextBlock's foreground to the foreground set in the control. A whole lot of properties are already available on the control due to its inheritance. The most interesting template binding is the one that binds the TextBlock's Text property. THis is interesting since there isn't a property called "Text" on the MyButton control. This has to be created, but first the control has to tell the system that it should use the new style/template.

In the constructor of the MyButton class, add a line of code that sets the "DefaultStyleKey" to "typeof(MyButton)". This tells the system that this control wants to use the style in the "generic.xaml" that has a TargetType that corresponds to this type. That's all that is needed.

public MyButton()
{
    DefaultStyleKey = typeof(MyButton);
}

If there is any interest in fetching parts of the template and handle those, this can be done by overriding the OnApplyTemplate() method and then getting hold of the parts by calling GetTemplateChild() passing in the name of the part. There will be more about parts and states in the next part of this tutorial...

Now, to the Text property. To be able to use a template binding, the property must be implemented as a DependencyProperty. This isn't very complicated, but necessary to make bindings work. Start off by adding a public and static DependencyProperty to the MyButton class. The naming standard says that it should be named the same thing as the property itself, but with a "Property" at the end. So in this case it should look like this:

public static DependencyProperty TextProperty;

A DependencyProperty isn't created, it is registered. In the registration the name of the property, the type of the property and the "owning" type must be supplied. The "owning" type is the type that declares the property. It is also possibe to give the property a default value as well as register a callback method that is called when the property is changed. The complete DependencyProperty declaration looks like this:

public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyButton), new PropertyMetadata(""));

Next the actual property of the MyButton type needs to be implemented. Since MyButton inherits from DependencyObject, it has one method for getting the value of a DependencyProperty as well as one to set one. They are, not surprisingly, called GetValue() and SetValue() and works with object. So the property should look something like this

public string Text
{
    get { return (string)GetValue(MyButton.TextProperty); }
    set { SetValue(MyButton.TextProperty, value); }
}

Now the layout of the button is actually done and it can be tested. There still has to be some functionality added to the control, but it will now show up if added to a page. So add a reference from the Silverlight Application project to the MyButton project. Then open up the Page.xaml file and add an xml-namespace pointing to the new assembly and also add an instance of the button. It looks like this:

<UserControl x:Class="MyButtonTest.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:btn="clr-namespace:MyButton;assembly=MyButton"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <btn:MyButton Width="100" Height="50" Text="Hello World" Background="Yellow" Foreground="Black" />
    </Grid>
</UserControl>

This should give you a view of how the control looks. The final thing to do is add some functionality. There is no use creating a control, if it doesn't have any functionality. The functionality added in this part of the 2-part tutorial, is a click event. Not very exciting, but it is some functionality. The Click event will be based on MouseLeftButonUp combined with a bool keeping track if the mousebutton was pressed down on the control too. Just handling MouseLeftButtonUp means handling a situation where the mousebutton was pressed outside of the control and then released on top of this control. So start off by adding a bool to keep track if the button has been pressed. Then add eventhandlers for MouseLeftButtonDown and Up as well as for the MouseLeave event. In the "down" handler, set the bool to true. In the "leave" set it to false. And in the "up", check to see if it is true. If it is true in the "up" event it is time to raise the Click event. Before it can be raised, it of course has to be added. Then of course set it to false before exiting the handler The code looks like this:

bool _mousePressed = false;

public MyButton()
{
    DefaultStyleKey = typeof(MyButton);
    this.MouseLeave += new MouseEventHandler(MyButton_MouseLeave);
    this.MouseLeftButtonDown += new MouseButtonEventHandler(MyButton_MouseLeftButtonDown);
    this.MouseLeftButtonUp += new MouseButtonEventHandler(MyButton_MouseLeftButtonUp);
}

void MyButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    _mousePressed = true;
}
void MyButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    if (_mousePressed)
    {
        OnClick();
    }
    _mousePressed = false;
}

void MyButton_MouseLeave(object sender, MouseEventArgs e)
{
    _mousePressed = false;
}

protected void OnClick(MouseEventArgs e)
{
    if (Click != null)
        Click(this, e);
} 

public event EventHandler<MouseEventArgs> Click;

This code is the final code for the control for this part of the tutorial. I know that the idea of setting the _mousePressed to false on MouseLeave stinks, but it's the simple way of handling it. It should probablybe handled a bit more logical, but that isn't really the goal of this blog post. The post is about the mechanics of creating a control, not about how to build a good button. There is already a button in the framework, so the control is not really useful anyway...
To see that it works, compile the project and add a click handler to the MyButton control in the Silverlight Applications Page.xaml. Something like this:

Page.xaml

<btn:MyButton Width="100" Height="50" Text="Hello World" Background="Yellow" Foreground="White" Click="MyButton_Click" />

Page.xaml.cs

private void MyButton_Click(object sender, MouseEventArgs e)
{
    MyButton.MyButton btn = (MyButton.MyButton)sender;
    btn.Text = "Hello again";
}

The next part will be about the parts and states model. Mostly about states, but parts will be mentioned. This control doesn't have any parts which makes it a bit hard to talk about, but it will have some states added to it so that the look can be changed when the mouse is over, the mousebutton is pressed and so on. Stay tuned for that...

+ Recent posts