MaterialDesignInXAML / MaterialDesignInXamlToolkit

Google's Material Design in XAML & WPF, for C# & VB.Net.
http://materialdesigninxaml.net
MIT License
15.14k stars 3.43k forks source link

Slider - (double) values issues #2685

Closed adisapir closed 2 years ago

adisapir commented 2 years ago

Issue: when Slider tick frequency changes is not an int numbers (e.g. 0.1) some values are shown as "near value". Image below shows the prob, XAML is for a quick repro.

Spotted on MaterialDesignThemes 4.5.0

image

Repro XAML:


                    <Slider
                        x:Name="SliderTimerInterval"
                        materialDesign:ValidationAssist.UsePopup="True"
                        AutoToolTipPlacement="None"
                        IsSnapToTickEnabled="True"
                        LargeChange="0.5"
                        Maximum="2"
                        Minimum="0.2"
                        Style="{StaticResource MaterialDesignDiscreteSlider}"
                        TickFrequency="0.1"
                        TickPlacement="Both"
                        ValueChanged="SliderTimerInterval_ValueChanged"
                        Value="{Binding Source={x:Static properties:Settings.Default}, Path=RefreshIntervalSeconds, Mode=TwoWay}" />
cjmurph commented 2 years ago

I can replicate this when the bound property is a float, but it works as expected when the property is a double. I have played around and managed to get a solution by adding an attached property "SliderAssist.ToolTipFormat". This would let you specify the tooltip format to be whatever you want, including specifiying a precision. Is this the way you'd like to solve this? I am happy to do a PR to add the attached property. here's an example: image

    <Slider 
    x:Name="SliderFloat"    
    wpf:SliderAssist.ToolTipFormat="the value is {0:F1} elephants"
    wpf:ValidationAssist.UsePopup="True"
    AutoToolTipPlacement="None"
    IsSnapToTickEnabled="True"
    LargeChange="0.5"
    Maximum="2"
    Minimum="0.2"
    Style="{StaticResource MaterialDesignDiscreteSlider}"
    TickFrequency="0.1"
    TickPlacement="Both"
    ValueChanged="SliderTimerInterval_ValueChanged" Margin="30,0"
    Value="{Binding RefreshIntervalFloat, Mode=TwoWay}"/>
adisapir commented 2 years ago

@cjmurph Thanks for looking into this! Your solution can be used as a workaround. I still believe it's a bug as the TickFrequency is double and the expected behavior is for the values to align with it, especially when IsSnapToTickEnabled="True". BTW, I noticed that this works fine with Style="{StaticResource MaterialDesignSlider} instead of Style="{StaticResource MaterialDesignDiscreteSlider}"

cjmurph commented 2 years ago

@adisapir when you tested, was the bound property (RefreshIntervalSeconds) a double or a float (single)? I couldn't replicate with a double, only with a float.

Changing the style to MaterialDesignSlider means you dont have the value label anymore. If you do see a label, its from the base controls AutoToolTip implementation. The AutoToolTip has a position and precision (AutoToolTipPosition and AutoToolTipPrecision), you can probably use these with MaterialDesignSlider to achieve what you need.

Fundamentally, applying the value of a floating point number to another floating point with different precision will yield unexpected results. The Slider control Value property comes from RangeBase and is a double. If you bind that to a float it will do... this. I think this is out of scope for this library to fix tbh.

adisapir commented 2 years ago

@adisapir when you tested, was the bound property (RefreshIntervalSeconds) a double or a float (single)? I couldn't replicate with a double, only with a float.

Changing the style to MaterialDesignSlider means you dont have the value label anymore. If you do see a label, its from the base controls AutoToolTip implementation. The AutoToolTip has a position and precision (AutoToolTipPosition and AutoToolTipPrecision), you can probably use these with MaterialDesignSlider to achieve what you need.

Fundamentally, applying the value of a floating point number to another floating point with different precision will yield unexpected results. The Slider control Value property comes from RangeBase and is a double. If you bind that to a float it will do... this. I think this is out of scope for this library to fix tbh.

Sorry for the delay - I did bind it to a double.

adisapir commented 2 years ago

@Keboo / @cjmurph I'm still able to reproduce, even without binding the value. I'm not sure if that's related, but it happens when the Slider is nested in a TabItem.

Here's the full xaml. Copy/Paste should reproduce:

<Window x:Class="WpfSandbox_ChildResize.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="120"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <DockPanel Grid.Column="0" Background="Gray"/>
        <TabControl Grid.Column="1" Background="Green">
            <TabItem Header="Slider">
                <Slider
                        x:Name="SliderTimerInterval"
                        Grid.Column="1"
                        Width="Auto"
                        IsSnapToTickEnabled="True"
                        AutoToolTipPlacement="None"
                        LargeChange="0.5"
                        Maximum="2"
                        Minimum="0.2"
                        Style="{StaticResource MaterialDesignDiscreteSlider}"
                        TickFrequency="0.1"
                        TickPlacement="Both"
                        Value="0.5" />
            </TabItem>
        </TabControl>
    </Grid>
</Window>
image
ElieTaillard commented 2 years ago

@adisapir So the problem is not solved is it?

adisapir commented 2 years ago

Nope. Still there

Keboo commented 2 years ago

I don't believe this is an issue with this library and instead related to the Slide control directly. If you remove the Material Design Slider style and investigate the Value property (I used snoop) you will see the same values appear there.

tpoint75 commented 1 year ago

Th UI gets unresponsible if the Maximum is much higher than the TickFrequency! There should be a maximum of tixs that would be set to prevent this! (more ticks than horizontal pixels of the screen doesn't make sense..