Range slider metro style app

2019-07-27 05:55发布

问题:

I'm trying to make a range slider for metro style app, because it's not available. I'm trying to leverage an existing silverlight range slider, but it's not going to well. I changed the code a bit, but now it just shows the slider and I can't move the thumbs.

Here is the xaml code:

<UserControl x:Class="Mecoms_Mobile_App.RangeSlider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid x:Name="LayoutRoot" Background="White" VerticalAlignment="Top">

    <Grid.Resources>
        <ControlTemplate x:Key="buttonTemplate" TargetType="RepeatButton">
            <!-- just empty-->
            <Grid />
        </ControlTemplate>
        <ControlTemplate x:Key="sliderTemplate" TargetType="Slider">
            <Grid x:Name="HorizontalTemplate" Background="{TemplateBinding Background}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <RepeatButton Template="{StaticResource buttonTemplate}" IsTabStop="False" IsEnabled="False" x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton" Grid.Column="0"/>
                <Thumb IsTabStop="True" Height="18" x:Name="HorizontalThumb" Width="11" Grid.Column="1">
                    <Thumb.Template>
                        <ControlTemplate TargetType="Thumb">
                            <Rectangle Fill="Red"
                                       Stroke="Black"
                                       StrokeThickness="1" />
                        </ControlTemplate>
                    </Thumb.Template>
                </Thumb>
                <RepeatButton Template="{StaticResource buttonTemplate}" IsTabStop="False" IsEnabled="False" x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton" Grid.Column="2"/>
            </Grid>
        </ControlTemplate>

    </Grid.Resources>

    <Border BorderThickness="0,1,0,0" BorderBrush="Black" VerticalAlignment="Center" Height="1" 
            Margin="5,0,5,0"/>

    <Slider x:Name="LowerSlider"
            Minimum="{Binding Minimum}"
            Maximum="{Binding Maximum}"
            Value="{Binding LowerValue, Mode=TwoWay}"
            Margin="0,0,10,0"
            Template="{StaticResource sliderTemplate}"
            />

    <Slider x:Name="UpperSlider"
            Minimum="{Binding Minimum}"
            Maximum="{Binding Maximum}"
            Value="{Binding UpperValue, Mode=TwoWay}"
            Margin="10,0,0,0"
            Template="{StaticResource sliderTemplate}"
            />
</Grid>
</UserControl>

The code behind it:

public sealed partial class RangeSlider : UserControl
{
    public RangeSlider()
    {
        InitializeComponent();
        this.Loaded += new RoutedEventHandler(RangeSlider_Loaded);

        LayoutRoot.DataContext = this;
    }

    void RangeSlider_Loaded(object sender, RoutedEventArgs e)
    {
        LowerSlider.ValueChanged += LowerSlider_ValueChanged;
        UpperSlider.ValueChanged += UpperSlider_ValueChanged;
    }

    void UpperSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
    {
        LowerSlider.Value = Math.Min(UpperSlider.Value, LowerSlider.Value);
    }

    void LowerSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
    {
        UpperSlider.Value = Math.Max(UpperSlider.Value, LowerSlider.Value);
    }

    public double Minimum
    {
        get { return (double)GetValue(MinimumProperty); }
        set { SetValue(MinimumProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Minimum.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MinimumProperty =
        DependencyProperty.Register("Minimum", typeof(double), typeof(RangeSlider), new PropertyMetadata(0d));

    public double Maximum
    {
        get { return (double)GetValue(MaximumProperty); }
        set { SetValue(MaximumProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Maximum.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MaximumProperty =
        DependencyProperty.Register("Maximum", typeof(double), typeof(RangeSlider), new PropertyMetadata(1d));

    public double LowerValue
    {
        get { return (double)GetValue(LowerValueProperty); }
        set { SetValue(LowerValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for LowerValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty LowerValueProperty =
        DependencyProperty.Register("LowerValue", typeof(double), typeof(RangeSlider), new PropertyMetadata(0d));

    public double UpperValue
    {
        get { return (double)GetValue(UpperValueProperty); }
        set { SetValue(UpperValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for UpperValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UpperValueProperty =
        DependencyProperty.Register("UpperValue", typeof(double), typeof(RangeSlider), new PropertyMetadata(0d));
}

Is there something wrong with this code? Or is there another way to achieve this?

回答1:

Better late than never, but I was trying to get the same code to work. Add

<Rectangle x:Name="HorizontalDecreaseRect" Grid.Row="1"/>

before the Thumb element in the ControlTemplate. This will allow the thumb to move.