My application has tons of TextBox
controls where the user can enter numeric values. Most of these values are in some physical unit. This unit indicator is displayed at the right side of the TextBox
control.
That looks like the following sketch: [________] km (where the unit is "km")
Currently I have done this with StackPanel
instances everywhere. It's always the same pattern. That makes the XAML less readable than it should be.
I'm looking for a TextBox
control that already includes that TextBlock
at its side to display the unit.
My first try was a class derived from TextBox
, with a XAML file that replaces the Template
property like this:
<TextBox
x:Class="WpfApplication1.UnitTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="_this"
KeyboardNavigation.IsTabStop="False"
Style="{StaticResource {x:Type TextBox}}">
<TextBox.Template>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox
Foreground="{TemplateBinding Foreground}"
IsEnabled="{TemplateBinding IsEnabled}"
IsReadOnly="{Binding IsReadOnly, ElementName=_this}"
Style="{TemplateBinding Style}"
Text="{Binding Text, ElementName=_this}"
Width="{TemplateBinding Width}"
... lots more ...
VerticalAlignment="Center"/>
<TextBlock
Grid.Column="1"
Text="{Binding Unit, ElementName=_this}"
Margin="4,0,0,0"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</TextBox.Template>
</TextBox>
Unit
is a dependency property in my UnitTextBox
code-behind class:
public partial class UnitTextBox : TextBox
{
public static DependencyProperty UnitProperty = DependencyProperty.Register(
name: "Unit",
propertyType: typeof(string),
ownerType: typeof(UnitTextBox));
public string Unit
{
get { return (string) GetValue(UnitProperty); }
set { SetValue(UnitProperty, value); }
}
public UnitTextBox()
{
InitializeComponent();
}
}
Unfortunately, there's a number of issues with this approach. I need to pass through virtually all properties to the inner TextBox
as you can see (I abbreviated it here). Also, I'd like the Width
property to apply to the inner TextBox
as usual, not to the outer Grid
. Think I need a separate property for that and bind the inner TextBox
instance to that. And currently, the style that I set when using the UnitTextBox
class is ignored. I don't even know how to solve that.
Is there any possibility to create such a combined control with WPF? It should act like a TextBox
with all its event handlers, bindable properties etc., but already include that unit string in its appearance, assignable by an additional property.
Could I instead use a custom Style
that adds the TextBlock
somewhere around (but I think I need the outer Grid
for aligning things), and declare the unit with an attached property?