Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

From code: Change ScrollViewer's scrollbars'-style to touch

Touch:

enter image description here

Mouse:

enter image description here

How do I tell the ScrollViewer to start using the touch-style scrollbar from code?

Here's an example:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ScrollViewer Name="scrollViewer1" HorizontalScrollBarVisibility="Visible" >
        <Image Stretch="UniformToFill">
            <Image.Source>
                <BitmapImage x:Name="bitmapImage1" UriSource="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png"></BitmapImage>
            </Image.Source>
        </Image>
    </ScrollViewer>
</Grid>

And:

public sealed partial class MainPage : Page
{
    DispatcherTimer dispatcherTimer1 = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
    bool SE;

    public MainPage()
    {
        this.InitializeComponent();
        dispatcherTimer1.Tick += DispatcherTimer1_Tick;
        dispatcherTimer1.Start();
    }

    private void DispatcherTimer1_Tick(object sender, object e)
    {
        if (SE = !SE) bitmapImage1.UriSource = new Uri("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/se/se-icon.png");
        else bitmapImage1.UriSource = new Uri("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png");
        scrollViewer1.ChangeView(SE ? 1 : 0, SE ? 1 : 0, null);
    }
}

If you run this (at least on a touch enabled PC) the scrollbars will initially be touch. And if you then move the cursor over it with the mouse, it will change to mouse. and if you then touch it (after the scrollbars have been hidden) it will return to touch.

I want to tell it programmatically to change from one to the other. How can that be done? If the only way is by editing the template - how can that be done without hard coding the template ? Just fixing the detail that needs fixing. To be clear: I want to be able to call a method that will change from one to the other: void ChangeTo(bool mouse) { ... }. (Though, failing that, just forcing the ScrollViewer to always be in one mode, would be somewhat of a workaround.)

like image 545
ispiro Avatar asked Dec 22 '16 21:12

ispiro


People also ask

What is panning mode in ScrollViewer?

PanningMode. A value that specifies how ScrollViewer reacts to touch manipulation.

What is a ScrollViewer C#?

The ScrollViewer control encapsulates horizontal and vertical ScrollBar elements and a content container (such as a Panel element) in order to display other visible elements in a scrollable area. You must build a custom object in order to use the ScrollBar element for content scrolling.

How do I add a ScrollBar in WPF?

How to enable scrollbar in a WPF TextBox. The simplest way to add scrolling functionality to a TextBox control is by enabling its horizontal and vertical scrolling. The HorizontalScrollBarVisibility and VerticalScrollBarVisibility properties are used to set horizontal and vertical scroll bars of a TextBox.


1 Answers

Within default template there are 3 VisualStates defined: NoIndicator, TouchIndicator and MouseIndicator

Style of scroller thumb looks different depending on which state is currently set. To change controls state you can call

VisualStateManager.GoToState(scrollViewer1, "TouchIndicator");

but you would need to manually take care of all events and actions when this state may change.

But if you want to have always TouchIndicator visible then better solution in my opinion would be to implement CustomVisualStateManager, for example:

public class MyVisualStateManager : VisualStateManager
{
    protected override bool GoToStateCore(Control control, FrameworkElement templateRoot, 
        System.String stateName, VisualStateGroup group, VisualState state, System.Boolean useTransitions)
    {
        switch (stateName)
        {
            case "NoIndicator":
            case "TouchIndicator":
            case "MouseIndicator":
                base.GoToStateCore(control, templateRoot, "TouchIndicator", group, state, useTransitions);
                break;
        }
        return true;
    }
}

Then you need to copy the template from MSDN, set it to your ScrollViewer and put MyVisualStateManager within it:

<Style TargetType="ScrollViewer" x:Key="ScrollStyle">
        <Setter Property="HorizontalScrollMode" Value="Auto" />
        <Setter Property="VerticalScrollMode" Value="Auto" />
        <Setter Property="IsHorizontalRailEnabled" Value="True" />
        <Setter Property="IsVerticalRailEnabled" Value="True" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="ZoomMode" Value="Disabled" />
        <Setter Property="HorizontalContentAlignment" Value="Left" />
        <Setter Property="VerticalContentAlignment" Value="Top" />
        <Setter Property="VerticalScrollBarVisibility" Value="Visible" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ScrollViewer">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <VisualStateManager.CustomVisualStateManager>
                            <local:MyVisualStateManager/>
                        </VisualStateManager.CustomVisualStateManager>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="ScrollingIndicatorStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition From="MouseIndicator" To="NoIndicator">
                                        <Storyboard>
                                (... blabla ...)
</Style>

style set:

<ScrollViewer Name="scrollViewer1"  Style="{StaticResource ScrollStyle}" HorizontalScrollBarVisibility="Visible">

Now whenever your ScrollViewer state needs to be changed, you are ignoring what exact state it wants, setting TouchIndicator instead.

like image 144
RTDev Avatar answered Sep 30 '22 04:09

RTDev