来自代码:将 ScrollViewer's scrollbars'-style 更改为 touch

isp*_*iro 5 c# xaml win-universal-app uwp uwp-xaml

触碰:

在此处输入图片说明

鼠:

在此处输入图片说明

我如何告诉ScrollViewer开始使用代码中的触摸式滚动条?

下面是一个例子:

<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>
Run Code Online (Sandbox Code Playgroud)

和:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您运行此程序(至少在支持触摸的 PC 上),滚动条最初将是触摸的。然后如果你用鼠标将光标移到它上面,它就会变成鼠标。如果您随后触摸它(在隐藏滚动条之后),它将返回触摸。

我想以编程方式告诉它从一个更改为另一个。那怎么办呢?如果唯一的方法是编辑模板——如何在硬编码模板的情况下完成?只修复需要修复的细节。需要明确的是:我希望能够调用一种方法,该方法将从一种更改为另一种:void ChangeTo(bool mouse) { ... }。(不过,如果失败,只是强制 ScrollViewer 始终处于一种模式,这将是一种解决方法。)

RTD*_*Dev 2

在默认模板中定义了 3 个 VisualState:NoIndicator、TouchIndicator 和 MouseIndicator

根据当前设置的状态,滚动条拇指的样式看起来有所不同。要更改控件状态,您可以调用

VisualStateManager.GoToState(scrollViewer1, "TouchIndicator");
Run Code Online (Sandbox Code Playgroud)

但当此状态可能发生变化时,您需要手动处理所有事件和操作。

但如果你想让 TouchIndicator 始终可见,那么我认为更好的解决方案是实现 CustomVisualStateManager,例如:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要从 MSDN 复制模板,将其设置到 ScrollViewer 并将 MyVisualStateManager 放入其中:

<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>
Run Code Online (Sandbox Code Playgroud)

风格设定:

<ScrollViewer Name="scrollViewer1"  Style="{StaticResource ScrollStyle}" HorizontalScrollBarVisibility="Visible">
Run Code Online (Sandbox Code Playgroud)

现在,每当您的 ScrollViewer 状态需要更改时,您都会忽略它想要的确切状态,而是设置 TouchIndicator。