12-27-2018 09:29 AM
Hello,
I am interested in customizing the NI NumericTextBoxDouble WPF control. My goal is to end up with a NumericTextBoxDouble user control that looks like the screenshot below. For the custom control I would like to inherit from the NumericTextBoxDouble class (since it has all the functionality I need and is what my code currently uses) and then customize/override the controls appearance. I'm not exactly sure where to get started and I have few questions (I'm not even sure if these are the right questions to ask)...
Any advice is appreciated, thanks!
12-27-2018 01:43 PM - edited 12-27-2018 01:46 PM
The NumericTextBox is designed as a first-class WPF control, so it supports replacing the control template to customize the appearance of the existing control. You can create a derived control to add additional functionality, but it is not required for purely visual changes.
You can modify the control template in Visual Studio by right-clicking the control and selecting “Edit Template”. This will give you a local copy of the template to work from. Using that as a starting point, I was able to create this simplified control style (i.e. without any interaction triggers, or advanced configuration support):
<Style x:Key="CustomNumericTextBoxDoubleStyle" TargetType="{x:Type ni:NumericTextBoxDouble}">
<Setter Property="Padding" Value="5"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="Background" Value="#FF673AB7"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ni:NumericTextBoxDouble}">
<ControlTemplate.Resources>
<ScaleTransform x:Key="Flip" ScaleY="-1" />
<Style x:Key="SpinnerButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="0,-3,0,0"/>
<Setter Property="Background" Value="#FFB39DDB"/>
<Setter Property="Content" Value="⬆"/>
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="{TemplateBinding Background}"
CornerRadius="3,3,0,0"
>
<ContentPresenter Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ControlTemplate.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.75*"/>
<RowDefinition Height="1.00*"/>
<RowDefinition Height="0.75*"/>
</Grid.RowDefinitions>
<RepeatButton Grid.Row="0"
Style="{StaticResource SpinnerButtonStyle}"
Command="{x:Static niPrimitives:ControlCommands.IncrementCommand}"
/>
<TextBox x:Name="PART_ValueInput"
Grid.Row="1"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Cursor="IBeam"
CaretBrush="{TemplateBinding Foreground}"
Foreground="{TemplateBinding Foreground}"
TextAlignment="{TemplateBinding TextAlignment}"
Text="{Binding FormattedValue, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
/>
<RepeatButton Grid.Row="2"
Style="{StaticResource SpinnerButtonStyle}"
Command="{x:Static niPrimitives:ControlCommands.DecrementCommand}"
RenderTransform="{StaticResource Flip}"
/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using the custom style, and the engineering value formatter from this answer as a named resource in the code (this.Resources["SecondsFormatter"] = new EngineeringValueFormatter( "S0's'" );), the final example looks like this:
<ni:NumericTextBoxDouble Style="{DynamicResource CustomNumericTextBoxDoubleStyle}"
Value="0.5"
ValueFormatter="{StaticResource SecondsFormatter}"
/>