Vertical slider with labels on the ticker

10,949

So, I can now answer my own question and maybe help someone in the future who will try to acomplish the same. Like I said in the comment of my own question, just later I realized I could go to the msdn and get the proper vertical slider template instead of trying to adapt the horizontal one.

My current XAML is now:

<ControlTemplate x:Key="VerticalSlider" TargetType="{x:Type Slider}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto" MinWidth="{TemplateBinding Slider.MinWidth}"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <local:MyTickBarVertical Margin="0,0,0,10" x:Name="TopTick" SnapsToDevicePixels="True" Placement="Left" Fill="{StaticResource GlyphDarkBrush}" Width="4" />
            <Track Grid.Column="1" Name="PART_Track">
                <Track.DecreaseRepeatButton>
                    <RepeatButton 
      Style="{StaticResource SliderButtonStyle}"
      Command="Slider.DecreaseLarge" />
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <Thumb Style="{StaticResource SliderThumbStyle}" />
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <RepeatButton 
      Style="{StaticResource SliderButtonStyle}"
      Command="Slider.IncreaseLarge" />
                </Track.IncreaseRepeatButton>
            </Track>
            <TickBar 
  Name="BottomTick"
  SnapsToDevicePixels="True" 
  Grid.Column="2"
  Fill="Black"
  Placement="Right"
  Width="4"
  Visibility="Collapsed" />
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="TickPlacement" Value="TopLeft">
                <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
            </Trigger>
            <Trigger Property="TickPlacement" Value="BottomRight">
                <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
            </Trigger>
            <Trigger Property="TickPlacement" Value="Both">
                <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
                <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

and I had do make some small changes to my class, since now I'm using a proper vertical slider:

public class MyTickBarVertical : TickBar
{
    protected override void OnRender(DrawingContext dc)
    {
        Size size = new Size(base.ActualWidth, base.ActualHeight);
        int tickCount = (int)((this.Maximum - this.Minimum) / this.TickFrequency) + 1;
        if ((this.Maximum - this.Minimum) % this.TickFrequency == 0)
            tickCount -= 1;
        Double tickFrequencySize;
        // Calculate tick's setting
        //width to height
        tickFrequencySize = (size.Height * this.TickFrequency / (this.Maximum - this.Minimum));
        string text = "";
        FormattedText formattedText = null;
        double num = this.Maximum - this.Minimum;
        int i = 0;
        // Draw each tick text
        for (i = 0; i <= tickCount; i++)
        {
            text = Convert.ToString(Convert.ToInt32(this.Maximum) - Convert.ToInt32(this.Minimum + this.TickFrequency * i), 10);
            formattedText = new FormattedText(text, CultureInfo.GetCultureInfo("en-us"), FlowDirection.RightToLeft, new Typeface("Verdana"), 16, Brushes.Black);
            dc.DrawText(formattedText, new Point(0, (tickFrequencySize * i)));
        }
    }
}

getting now the following: http://s4.postimage.org/d0q6dpxvx/Correct.jpg

Cheers!

Share:
10,949

Related videos on Youtube

Santux
Author by

Santux

I'm a software engineer with major interests in ASP.NET (C#, DotNetNuke, WPF, SQL Server) and Mobile (Android).

Updated on September 14, 2022

Comments

  • Santux
    Santux over 1 year

    I'm currently trying to get a custom vertical slider with a ticker as well as labels in those tickers with the corresponding values. I already found online some interesting code for a horizontal slider that I'm now using in my solution and goes as follows:

    XAML:

    <ControlTemplate x:Key="HorizontalSlider" TargetType="{x:Type Slider}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto" MinHeight="{TemplateBinding Slider.MinHeight}"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <local:MyTickBar Margin="5,0,10,0" x:Name="TopTick" SnapsToDevicePixels="True" Placement="Top" Fill="{StaticResource GlyphDarkBrush}" Height="5"  />
                <Border Name="TrackBackground" Margin="0" CornerRadius="2" Height="4" Grid.Row="1" Background="{StaticResource GlyphLightBrush}" BorderBrush="{StaticResource ButtonNormal}" BorderThickness="1" />
                <Track Grid.Row="1" Name="PART_Track">
                    <Track.DecreaseRepeatButton>
                        <RepeatButton Style="{StaticResource SliderButtonStyle}" Command="Slider.DecreaseLarge" />
                    </Track.DecreaseRepeatButton>
                    <Track.Thumb>
                        <Thumb Style="{StaticResource SliderThumbStyle}" />
                    </Track.Thumb>
                    <Track.IncreaseRepeatButton>
                        <RepeatButton Style="{StaticResource SliderButtonStyle}" Command="Slider.IncreaseLarge" /> 
                    </Track.IncreaseRepeatButton>
                </Track>
                <TickBar Name="BottomTick" SnapsToDevicePixels="True" Grid.Row="2" Fill="Black" Placement="Bottom" Height="10" Visibility="Collapsed" />
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="TickPlacement" Value="TopLeft">
                    <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
                </Trigger>
                <Trigger Property="TickPlacement" Value="BottomRight">
                    <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
                </Trigger>
                <Trigger Property="TickPlacement" Value="Both">
                    <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
                    <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    

    With MyTickBar being a class defined as:

    public class MyTickBar : TickBar
    {
        protected override void OnRender(DrawingContext dc)
        {
            Size size = new Size(base.ActualWidth, base.ActualHeight);
            int tickCount = (int)((this.Maximum - this.Minimum) / this.TickFrequency) + 1;
            if ((this.Maximum - this.Minimum) % this.TickFrequency == 0)
                tickCount -= 1;
            Double tickFrequencySize;
            // Calculate tick's setting
            tickFrequencySize = (size.Width * this.TickFrequency / (this.Maximum - this.Minimum));
            string text = "";
            FormattedText formattedText = null;
            double num = this.Maximum - this.Minimum;
            int i = 0;
            // Draw each tick text
            for (i = 0; i <= tickCount; i++)
            {
                text = Convert.ToString(Convert.ToInt32(this.Minimum + this.TickFrequency * i), 10);
                formattedText = new FormattedText(text, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("Verdana"), 16, Brushes.Black);
                dc.DrawText(formattedText, new Point((tickFrequencySize * i), 30));
            }
        }
    }
    

    This works fine with a horizontal slider, but as I pretend a vertical one I tried 2 different solutions with no success. First, was to make a similar XAML for a vertical slider, but as I'm quite new to WPF, I couldn't achieve the intended solution (I basically changed the row and height properties to column and with, but is probably a bit more complex than that). And my second attempt was using a

    <Slider.LayoutTransform>
                <RotateTransform Angle="270"/>
            </Slider.LayoutTransform>
    

    on the pretended slider, getting a slider with the labels in the incorrect position, like the following image illustrates: http://s22.postimage.org/sophl10wh/Incorrect.jpg

    I tried to apply a rotation to the DrawingContext of MyTicker but that rotates the entire ticker, instead of the labels with the values. So, my question is how can I obtain the pretend solution? Either through the necessary changes to a new XAML for a custom vertical slider, or just rotating the labels in the second solution.

  • Zev Spitz
    Zev Spitz almost 11 years
    I am trying to implement something similar. What XAML did you use for the slider itself?
  • Santux
    Santux almost 11 years
    You should use the slider control template present in msdn.microsoft.com/en-us/library/ms753256(v=vs.85).aspx and I replaced one of the tickbars with: <local:MyTickBarVertical x:Name="TopTick" Visibility="Collapsed" Fill="{TemplateBinding Foreground}" SnapsToDevicePixels="True" Margin="0,0,0,20" Placement="Top" Width="4"/> where you define a class MyTickBarVertical : TickBar like the one I have in the answer.
  • Zev Spitz
    Zev Spitz almost 11 years
    And then what: <Slider Template={StaticResource VerticalSlider} /> and what else?
  • Santux
    Santux almost 11 years
    I used it as a style. In the App.xaml I defined <Style x:Key="MyCustomStyleForSliderVertical" TargetType="{x:Type Slider}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Slider}"> (...) and in your window or control you just apply that style to the control such as Style="{StaticResource MyCustomStyleForSliderVertical}"