[wpf] Good NumericUpDown equivalent in WPF?

I'm looking for a simple NumericUpDown (a.k.a. number spinner) control in WPF. This seems to be another lacking control in WPF. There must be some existing ones out there and I don't like to re-invent the wheel.

This question is related to wpf spinner numericupdown

The answer is


A control that is missing from the original set of WPF controls, but much used, is the NumericUpDown control. It is a neat way to get users to select a number from a fixed range, in a small area. A slider could be used, but for compact forms with little horizontal real-estate, the NumericUpDown is essential.

Solution A (via WindowsFormsHost)

You can use the Windows Forms NumericUpDown control in WPF by hosting it in a WindowsFormsHost. Pay attention that you have to include a reference to System.Windows.Forms.dll assembly.

<Window x:Class="WpfApplication61.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>    
        <WindowsFormsHost>
            <wf:NumericUpDown/>
        </WindowsFormsHost>
...

Solution B (custom)

There are several commercial and codeplex versions around, but both involve installing 3rd party dlls and overheads to your project. Far simpler to build your own, and a aimple way to do that is with the ScrollBar.

A vertical ScrollBar with no Thumb (just the repeater buttons) is in fact just what we want. It inherits rom RangeBase, so it has all the properties we need, like Min, Max, and SmallChange (set to 1, to restrict it to Integer values)

So we change the ScrollBar ControlTemplate. First we remove the Thumb and Horizontal trigger actions. Then we group the remains into a grid and add a TextBlock for the number:

<Grid Margin="2">
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <TextBlock VerticalAlignment="Center" FontSize="20" MinWidth="25" Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}}"/>
    <Grid Grid.Column="1" x:Name="GridRoot" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Background="{TemplateBinding Background}">
        <Grid.RowDefinitions>
            <RowDefinition MaxHeight="18"/>
            <RowDefinition Height="0.00001*"/>
            <RowDefinition MaxHeight="18"/>
        </Grid.RowDefinitions>
        <RepeatButton x:Name="DecreaseRepeat" Command="ScrollBar.LineDownCommand" Focusable="False">
            <Grid>
                <Path x:Name="DecreaseArrow" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Data="M 0 4 L 8 4 L 4 0 Z"/>
            </Grid>
        </RepeatButton>
        <RepeatButton Grid.Row="2" x:Name="IncreaseRepeat" Command="ScrollBar.LineUpCommand" Focusable="False">
            <Grid>
                <Path x:Name="IncreaseArrow" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Data="M 0 0 L 4 4 L 8 0 Z"/>
            </Grid>
        </RepeatButton>
    </Grid>
</Grid>

Sources:


If commercial solutions are ok, you may consider this control set: WPF Elements by Mindscape

It contains such a spin control and alternatively (my personal preference) a spin-decorator, that can decorate various numeric controls (like IntegerTextBox, NumericTextBox, also part of the control set) in XAML like this:

<WpfElements:SpinDecorator>
   <WpfElements:IntegerTextBox Text="{Binding Foo}" />
</WpfElements:SpinDecorator>

add a textbox and scrollbar

in VB

Private Sub Textbox1_ValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.RoutedPropertyChangedEventArgs(Of System.Double)) Handles Textbox1.ValueChanged
     If e.OldValue > e.NewValue Then
         Textbox1.Text = (Textbox1.Text + 1)
     Else
         Textbox1.Text = (Textbox1.Text - 1)
     End If
End Sub

If commercial solutions are ok, you may consider this control set: WPF Elements by Mindscape

It contains such a spin control and alternatively (my personal preference) a spin-decorator, that can decorate various numeric controls (like IntegerTextBox, NumericTextBox, also part of the control set) in XAML like this:

<WpfElements:SpinDecorator>
   <WpfElements:IntegerTextBox Text="{Binding Foo}" />
</WpfElements:SpinDecorator>

A control that is missing from the original set of WPF controls, but much used, is the NumericUpDown control. It is a neat way to get users to select a number from a fixed range, in a small area. A slider could be used, but for compact forms with little horizontal real-estate, the NumericUpDown is essential.

Solution A (via WindowsFormsHost)

You can use the Windows Forms NumericUpDown control in WPF by hosting it in a WindowsFormsHost. Pay attention that you have to include a reference to System.Windows.Forms.dll assembly.

<Window x:Class="WpfApplication61.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>    
        <WindowsFormsHost>
            <wf:NumericUpDown/>
        </WindowsFormsHost>
...

Solution B (custom)

There are several commercial and codeplex versions around, but both involve installing 3rd party dlls and overheads to your project. Far simpler to build your own, and a aimple way to do that is with the ScrollBar.

A vertical ScrollBar with no Thumb (just the repeater buttons) is in fact just what we want. It inherits rom RangeBase, so it has all the properties we need, like Min, Max, and SmallChange (set to 1, to restrict it to Integer values)

So we change the ScrollBar ControlTemplate. First we remove the Thumb and Horizontal trigger actions. Then we group the remains into a grid and add a TextBlock for the number:

<Grid Margin="2">
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <TextBlock VerticalAlignment="Center" FontSize="20" MinWidth="25" Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}}"/>
    <Grid Grid.Column="1" x:Name="GridRoot" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Background="{TemplateBinding Background}">
        <Grid.RowDefinitions>
            <RowDefinition MaxHeight="18"/>
            <RowDefinition Height="0.00001*"/>
            <RowDefinition MaxHeight="18"/>
        </Grid.RowDefinitions>
        <RepeatButton x:Name="DecreaseRepeat" Command="ScrollBar.LineDownCommand" Focusable="False">
            <Grid>
                <Path x:Name="DecreaseArrow" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Data="M 0 4 L 8 4 L 4 0 Z"/>
            </Grid>
        </RepeatButton>
        <RepeatButton Grid.Row="2" x:Name="IncreaseRepeat" Command="ScrollBar.LineUpCommand" Focusable="False">
            <Grid>
                <Path x:Name="IncreaseArrow" Stroke="{TemplateBinding Foreground}" StrokeThickness="1" Data="M 0 0 L 4 4 L 8 0 Z"/>
            </Grid>
        </RepeatButton>
    </Grid>
</Grid>

Sources:


add a textbox and scrollbar

in VB

Private Sub Textbox1_ValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.RoutedPropertyChangedEventArgs(Of System.Double)) Handles Textbox1.ValueChanged
     If e.OldValue > e.NewValue Then
         Textbox1.Text = (Textbox1.Text + 1)
     Else
         Textbox1.Text = (Textbox1.Text - 1)
     End If
End Sub