Introduction
Silverlight 2.0 developer can add a control by:
- copying control's XAML directly in application's XAML - this way the control is not reusable, developer must clone code to provide another control
- creating
UserControl
- but UserControl
is a container, heavy control
- creating custom control - lightweight, more efficient for multiplying
Background
The official Microsoft way for creating a custom control would be: create Silverlight Class Library, add generic.xaml to the project, create a class derived from Control
, etc. A short tutorial can be found here.
Since all XAML is stored in generic.xaml, the file gets larger and modifying a large file is a problem. Imagine you have 10 controls and want to copy an animation from the first control to the last one. Scrolling and locating code can be time consuming.
What if the custom control would be created like UserControl
- XAML file and code-behind. A developer could easily switch between those two parts. This article describes a technique to organize custom controls.
Step by Step
Create a new UserControl
to get *.xaml and code-behind file (*.cs, *.vb).
Select *.xaml and change Build Action to Resource.
Open *.xaml file and replace UserControl tag with ResourceDictionary, remove also Width
, Height
and x:Class
attributes.
Open *.cs file. Replace UserControl
with Control
, remove InitializeComponent();
from constructor. Add Loaded event handler and call static
method for loading style from XAML.
A custom control is created but does not have any functionality. To make it useful, add Style, Storyboards, visual elements to the *.xaml and create overridden OnApplyTemplate()
in *.cs. Articles on designing and programming custom controls can be found on The Code Project or on the internet.
Loader Class
Loader class for this sample contains the static LoadStyle(Control control)
method. The method gets the control name from type, loads XAML from resources and applies style to the control.
Code
public static void LoadStyle(Control control)
{
try
{
int b;
List<byte> bytes = new List<byte>();
string name = control.GetType().Name;
string assembly = "development";
string directory = "Controls/";
string path = string.Format(
"/{0};component/{1}{2}.xaml",
assembly, directory, name);
StreamResourceInfo info = Application.GetResourceStream(
new Uri(path, UriKind.Relative));
while ((b = info.Stream.ReadByte()) >= 0)
{
bytes.Add((byte)b);
}
string xaml = Encoding.UTF8.GetString(
bytes.ToArray(), 0, bytes.Count);
object obj = XamlReader.Load(xaml);
if (obj != null && obj is ResourceDictionary)
{
string key = name + "Style";
control.Style = (Style)((ResourceDictionary)obj)[key];
}
}
catch
{
}
}
Points of Interest
In WPF, custom control styles can be linked in ResourceDictionary.MergedDictionaries
. Silverlight does not (yet) have that feature.
History
- 7th November, 2008: Initial post