More and more I see sites supporting OpenID as Authentication mechanism. I’m for example a user of sites like: I need to read this, Get Satisfaction and Google Login more or less.
To support my own family I set up OpenID on my own domain, http://openid.mymonster.nl/ hosted by MyOpenID. This just works like a charm. For the purpose of this article I created a test identity at my MyOpenID. I suggest everyone doing development for openid connectivity to create a test identity, I don’t want to mess with my real OpenID identity. This is part one of a three part series on the creation of an OpenID User Control. I initially created the control for use in my own application and have submitted it to the Silverlight Control Builder Contest of 2009.
UI Design
One of the first things I was thinking about, was my design capacities. I came up with the following design, before signing in.
After you have signed in.
Yes I know, it’s very straightforward, and all the designers in this world could have thought about a better alternative. That’s why I thought this control to require the ability to template it. There are some articles on the web about templating Silverlight User Controls, this one helped me a lot.
To support Templating for a user control it needs to inherit ContentControl
Visually I identified two states:
- Unauthenticated – This state is active when the user hasn’t signed in yet.
- Authenticated – This state is active when the user has successfully signed in.
If the sign in was successful the control will move to the authenticated state. These Visual States can be used in the Xaml part of the user control, which we will do later on.
As you can see in the above pictures we can think about three essential parts in this control.
- LoginButton, typeof(Button)
- IdentityInput, typeof(TextBox)
- IdentitySuccessLabel, typeof(TextBlock)
When you combine just these parts the C# file will look like this. (Please note, some parts are left out for the clear picture).
[TemplatePart(Name = LoginButton, Type = typeof(Button))]
[TemplatePart(Name = IdentityInput, Type = typeof(TextBox))]
[TemplatePart(Name = IdentitySuccessLabel, Type = typeof(TextBlock))]
[TemplateVisualState(Name = VisualStates.Unauthenticated, GroupName = VisualStates.CommonStates)]
[TemplateVisualState(Name = VisualStates.Authenticated, GroupName = VisualStates.CommonStates)]
public class OpenIdLoginControl : ContentControl
{
private const string IdentityInput = "IdentityInput";
private const string IdentitySuccessLabel = "IdentitySuccessLabel";
private const string LoginButton = "LoginButton";
private TextBox m_identityInput;
private TextBlock m_identitySuccessLabel;
private Button m_loginButton;
public OpenIdLoginControl()
{
DefaultStyleKey = typeof(OpenIdLoginControl);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
m_identityInput = (TextBox)GetTemplateChild(IdentityInput);
m_loginButton = (Button)GetTemplateChild(LoginButton);
m_identitySuccessLabel = (TextBlock)GetTemplateChild(IdentitySuccessLabel);
}
#region Nested type: VisualStates
private static class VisualStates
{
internal const string Authenticated = "Authenticated";
internal const string CommonStates = "CommonStates";
internal const string Unauthenticated = "Unauthenticated";
}
#endregion
}
To give this control a default style there needs to be a Themes directory and a xaml-file called Generic.xaml inside the library which will contain this control. The Generic.xaml file is a ResourceDictionary, and in this case we add a style for the OpenIdLoginControl. The xaml file kind of looks like the following (I removed the VisualStateManager parts for the VisualStates).
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
xmlns:openid="clr-namespace:MM.OpenId.Controls">
<Style TargetType="openid:OpenIdLoginControl">
<Setter Property="Width" Value="330" />
<Setter Property="Height" Value="50" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="openid:OpenIdLoginControl">
<Border BorderBrush="Black" CornerRadius="4" BorderThickness="1">
<Grid x:Name="LayoutRoot" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Grid.Row="0" Source="/MM.OpenId.Controls;component/openid-icon.png" Width="30" Height="30" Margin="8"/>
<TextBlock Grid.Column="1" Grid.Row="0" x:Name="IdentitySuccessLabel" VerticalAlignment="Center" Margin="8" HorizontalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="0" x:Name="IdentityInput" Text="http://openid.mymonster.nl/demo" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="8" />
<Button Grid.Column="2" Grid.Row="0" x:Name="LoginButton" Content="Sign In" Margin="8" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>Because this is just the default template, you can change this to adjust it to your own application.
Because the extreme size of this article I’ve split this article into multiple articles. I will provide the full source at the end of the last article. You can expect at least the following two parts:
- OpenID Integration
- Integration in your own application
Ps. This article is cross posted on: Mark Monster’s blog and Silverlight Help.


