Creating a Simple User Control in C#

Why User Controls?

For most of my projects, the built-in controls of Visual Studio are good enough to cover my needs. But once in awhile, I find the need for a complex control built specifically for a certain project. This is where UserControls come in handy, and as we will see, can be very powerful and not nearly as difficult as they might sound.

Some good reasons to use User Controls:

  • Portability: Once you have defined a User Control, it is easy to move that control within a projects or move to other projects

  • Abstraction: By separating out functionality and encapulating it under a User Control, the code will become much cleaner and easier for others to use

In my current teacher aid app, I wanted to display "desks" that represented students. Now, I could have done this just as easily within the XAML, but using a User Control gives me more flexibility and cleaner code - which will all pay off later down the road.

Creating a User Control

To start, create a new project in Visual Studio (I'm using VS2013). Any Visual C# project will do, but I'll be using a Windows Store (WinRT/Windows 8) app for this example.

Next, go to Project -> Add New Item and select User Control from the list. Give it an appropriate name and hit Add.

Before we start to create our new User Control, its important to remember that a User Control is simply a "control of controls" and is functionally similar to any other XAML page you might create. Essentially you are simply creating a smaller "page" that will be placed into the larger page. That means all the fun stuff in the toolbox is available for you.

XAML

Here is the XAML code for my desk:

<UserControl
    x:Class="TeacherMate.DeskControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TeacherMate"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="200"
    d:DesignWidth="200"
    x:Name="DeskUC">

    <Border x:Name="deskBorder" BorderBrush="{Binding ElementName=DeskUC, Path=BorderColor}" BorderThickness="3">
        <Grid x:Name="LayoutRoot">

            <Grid.RowDefinitions>
                <RowDefinition Height="3*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Grid.Background>
                <ImageBrush Stretch="Fill" ImageSource="ms-appx:///Images/desk.png" />
            </Grid.Background>

            <Image x:Name="imgStudentPhoto" Grid.Row="0" Source="{Binding ElementName=DeskUC, Path=StudentPhoto}" Margin="0" Stretch="UniformToFill" />

            <Rectangle x:Name="rectName" Grid.Row="1" Fill="{Binding ElementName=DeskUC, Path=BorderColor}" />

            <StackPanel x:Name="spName" Grid.Row="1" VerticalAlignment="Center">
                <Viewbox Stretch="Uniform" StretchDirection="DownOnly">
                    <TextBlock x:Name="txtName" Grid.Row="1" Margin="15" Text="Joe Williams" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" FontSize="24" />
                </Viewbox>
            </StackPanel>
        </Grid>
    </Border>
</UserControl>

And here is the simple XAML rendering:

The Desk includes a few key components:

  • Border: I wanted a border with the ability to change colors to reflect the status of a student

  • Image: Displays an image (or picture) of each student

  • Name Text: Displays each students name

A few other things to point out. First, you'll notice under UserControl attributes I have given it both a design height and width. You can always resize the control when you use it, but this sets the default size and a baseline for design. Also, I've named it using x:Name="DeskUC" so I can reference it with code.

Code

Before we dive into the code, we should talk binding. I wanted all of the components I discussed earlier to be bindable. This can be a bit tricky if you are only used to binding to something, as we now have to create something to bind from. Normally when binding to a control, I can just create a property and bind to a property of the control. Well, the property of that control is a special type of property known as a DependencyProperty. So, we need to create some of those in order for our User Control to support binding.

Open up your UserControl.xaml.cs and add the following lines of code:

    public string StudentName {
        get { return (string)GetValue(StudentNameProperty); }
        set { SetValue(StudentNameProperty, value); }
    }

    public static readonly DependencyProperty StudentNameProperty = DependencyProperty.Register(
        "StudentName",
        typeof(string),
        typeof(DeskControl),
        new PropertyMetadata(string.Empty, StudentNamePropertyChanged));

    private static void StudentNamePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

    }

First, I created a basic string property StudentName to hold the string of the student name. Then, I created a Dependency Property and registered the former property. Make certain that the first parameter of the Register method matches "StudentName" property or you will receive an error. The next two parameters are simply the type of the property and the type of its parent. The last parameter is any property metadata we want to register - in this case we'll attach a PropertyChanged method that fires when the property is modified (yes - just like it sounds), which is defined right below.

Now StudentName is exposed for binding. However, at this point, only the string property is bound, not the actual text on the XAML page created earlier. There are two options at this point. We can either bind the XAML text to the property as well, or we can add in some code to the Property Changed method - both should have the same effect:

private static void StudentNamePropertyChanged(DependencyObject d DependencyPropertyChangedEventArgs e)
    {
        DeskControl dc = d as DeskControl;
        dc.txtName.Text = e.NewValue as string;
    }

The rest of the properties follow a similar pattern with the final User Control looking something like this:

Wrap Up

Now I have a desk control that I can bind with a student, which gives me an easy way to display a class of students, and instant updates on changing student data. Clearly this is a simple example, but hopefully it shows the advantage of using User Controls.

Brandon Brown

Read more posts by this author.