C# – Creating a custom UI element in WPF

cwpfxaml

I have a several TextBoxes with Labels in my code which are implemented with the following XAML:

<DockPanel HorizontalAlignment="Right">
    <TextBlock Foreground="Black" Padding="0,0,10,0">Serial Number:</TextBlock>
    <TextBox Width="150" IsReadOnly="True" BorderBrush="Gainsboro" Height="20"></TextBox>
</DockPanel>

I can reduce some of the copied code by doing something like:

<DockPanel HorizontalAlignment="Right">
    <TextBlock Style="{StaticResource CstmTextBoxLbl}">Serial Number:</TextBlock>
    <TextBox Style="{StaticResource CstmTextBox}"></TextBox>
</DockPanel>

but it is still somewhat lengthy. Is it possible to do something like:

<controls:CstmTextBox Style="{StaticResource CstmTextBox}" LabelText="Serial Number:" Text=""/>

Where the CstmTextBox would implement the whatever XAML is needed to get the same visual effect once, and I could access both the TextBlock text and the TextBox text in the code. Such as

CstmTextBox textbox;
textbox.LabelText = "Serial Number:";
String some_text = textbox.Text;

textbox.Text = "....";

Best Answer

A UserControl or a CustomControl serves your needs. This is the code for a CustomControl.

C#:

public class CstmTextBox : Control
{
    public string LabelText
    {
        get
        {
            return (string)GetValue (LabelTextProperty);
        }
        set
        {
            SetValue (LabelTextProperty, value);
        }
    }

    public static readonly DependencyProperty LabelTextProperty =
        DependencyProperty.Register ("LabelText", typeof (string), typeof (CstmTextBox), new PropertyMetadata (string.Empty));

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

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register ("Text", typeof (string), typeof (CstmTextBox), new PropertyMetadata (string.Empty));
}

XAML:

    <Style TargetType="{x:Type controls:CstmTextBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:CstmTextBox}">
                    <DockPanel HorizontalAlignment="Right">
                        <TextBlock Foreground="Black" Padding="0,0,10,0" Text="{TemplateBinding LabelText}"/>
                        <TextBox Width="150" IsReadOnly="True" BorderBrush="Gainsboro" Height="20" Text="{TemplateBinding Text}"/>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Add the style to your resources and use the new control:

    <controls:CstmTextBox LabelText="abcde" Text="1234"/>