wpfdata-bindingcontroltemplate

Is there a way to trigger a Value change event withing the ControlTemplate for a Slider


I am trying to come up with a ControlTemplate that will make a Slider look like a NumericUpDown control.

It has a Grid with three columns, where there will be a decrement button, a TextBlock showing the current value, and an increment button.

Yes, I know there are some imitations of NumericUpDown control in WPF which use code-behind, or custom controls in some libraries, but I am looking for a sneaky way to increment and decrement the value by adding EventTriggers to Click events of the buttons on the template.

Could I achieve my goal by invoking ValueChanged or other slider events in those EventTriggers?

Note: A Storyboard with a DoubleAnimation almost worked, but, alas, I could not bind the "To" property of the animation to the incremented or decremented Value property of the Slider itself, because of the Freezable issue.


Solution

  • The standard Slider has the commands to incrememt or decrement values and a simple custom ControlTemplate for Slider will suffice.

    <Style x:Key="NumericUpDownStyle" TargetType="{x:Type Slider}">
        <Setter Property="Width" Value="120"/>
        <Setter Property="Height" Value="30"/>
        <Setter Property="Foreground" Value="Black"/>
        <Setter Property="Ticks" Value="1"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Slider}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="30"/>
                            <ColumnDefinition/>
                            <ColumnDefinition Width="30"/>
                        </Grid.ColumnDefinitions>
    
                        <!-- Decrement button -->
                        <RepeatButton Grid.Column="0"
                                      Command="Slider.DecreaseLarge"
                                      FontFamily="Segoe MDL2 Assets" FontSize="16"
                                      Content="&#xE973;"
                                      Focusable="False"/>
    
                        <Border Grid.Column="1"
                                BorderBrush="Gray"
                                BorderThickness="1">
                            <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
                                       FontSize="20"
                                       Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}}"/>
                        </Border>
    
                        <!-- Increment button -->
                        <RepeatButton Grid.Column="2"
                                      Command="Slider.IncreaseLarge"
                                      FontFamily="Segoe MDL2 Assets" FontSize="16"
                                      Content="&#xE974;"
                                      Focusable="False"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>