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 = "....";
Create a new WPF project and then right-click on your solution and select Add > New Item... It will open the following window. Now select Custom Control (WPF) and name it MyCustomControl. Click the Add button and you will see that two new files (Themes/Generic.
UIElement is a base class for WPF core level implementations building on Windows Presentation Foundation (WPF) elements and basic presentation characteristics.
User Interface Panels. There are six panel classes available in UI scenarios: Canvas, DockPanel, Grid, StackPanel, VirtualizingStackPanel, and WrapPanel.
User controls, in WPF represented by the UserControl class, is the concept of grouping markup and code into a reusable container, so that the same interface, with the same functionality, can be used in several different places and even across several applications.
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"/>
Add a UserControl
to your solution, and copy the XAML you want to reuse inside.
If you set x:Name
to the controls inside your UserControl
...
<UserControl ... >
<DockPanel HorizontalAlignment="Right">
<TextBlock x:Name="SerialNumberTextBlock" Style="{StaticResource CstmTextBoxLbl}">Serial Number:</TextBlock>
<TextBox x:Name="SerialNumberTextBox" Style="{StaticResource CstmTextBox}"></TextBox>
</DockPanel>
</UserControl>
... you'll be able to access them from outside (code-behind) like this:
CstmTextBox textbox;
textbox.SerialNumberTextBlock.Text = "Serial Number:";
String some_text = textbox.SerialNumberTextBox.Text;
textbox.SerialNumberTextBox.Text = "....";
But it's even better if you create DependencyProperties for the properties you want to expose. You define those properties in the code-behind of your UserControl:
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue (TextProperty, value);
}
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof (CstmTextBox));
Then bind those properties to the controls inside your UserControl:
<UserControl x:Name="Root" ... >
<DockPanel HorizontalAlignment="Right">
<TextBlock x:Name="SerialNumberTextBlock" Style="{StaticResource CstmTextBoxLbl}"
Text="{Binding LabelText, ElementName=Root}" />
<TextBox x:Name="SerialNumberTextBox" Style="{StaticResource CstmTextBox}"
Text="{Binding Text, ElementName=Root, Mode=TwoWay}" />
</DockPanel>
</UserControl>
That way you can set the properties directly from outside, be it code-behind, XAML or Binding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With