【问题标题】:Making ScrollViewer's ScrollBar always visible through overriding or styling通过覆盖或样式使 ScrollViewer 的 ScrollBar 始终可见
【发布时间】:2014-09-23 08:20:58
【问题描述】:

我正在尝试使 ScrollViewer 的 ScrollBar 始终可见,因此它不仅在我尝试滚动文本视图时出现,而且用户知道还有更多内容要查看。 刚开始不知什么原因,我以为我只需要更改需要覆盖画笔的颜色,但实际上,滚动条正在淡入淡出,因此需要更改 ScrollViewer 或 ScrollBar 的模板。

我找到了刚刚放在 App.Resources 部分中的 ScrollViewer 模板,但我不知道如何编辑它,因此 ScrollBar 始终可见:

<Style TargetType="ScrollViewer">
    <Setter Property="HorizontalScrollMode" Value="Enabled" />
    <Setter Property="VerticalScrollMode" Value="Enabled" />
    <Setter Property="IsHorizontalRailEnabled" Value="True" />
    <Setter Property="IsVerticalRailEnabled" Value="True" />
    <Setter Property="IsTabStop" Value="False" />
    <Setter Property="ZoomMode" Value="Enabled" />
    <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.VisualStateGroups>
                        <VisualStateGroup x:Name="ScrollingIndicatorStates">
                            <VisualStateGroup.Transitions>
                                <VisualTransition From="MouseIndicator" To="NoIndicator">
                                    <Storyboard>
                                        <FadeOutThemeAnimation TargetName="ScrollBarSeparator" BeginTime="0:0:3" />
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar"
                                                                   Storyboard.TargetProperty="IndicatorMode">
                                            <DiscreteObjectKeyFrame KeyTime="0:0:3">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <ScrollingIndicatorMode>None</ScrollingIndicatorMode>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar"
                                                                   Storyboard.TargetProperty="IndicatorMode">
                                            <DiscreteObjectKeyFrame KeyTime="0:0:3">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <ScrollingIndicatorMode>None</ScrollingIndicatorMode>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualTransition>
                                <VisualTransition From="TouchIndicator" To="NoIndicator">
                                    <Storyboard>
                                        <FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar"
                                                                   Storyboard.TargetProperty="IndicatorMode">
                                            <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <ScrollingIndicatorMode>None</ScrollingIndicatorMode>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar"
                                                                   Storyboard.TargetProperty="IndicatorMode">
                                            <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <ScrollingIndicatorMode>None</ScrollingIndicatorMode>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualTransition>
                            </VisualStateGroup.Transitions>

                            <VisualState x:Name="NoIndicator">
                                <Storyboard>
                                    <FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="TouchIndicator">
                                <Storyboard>
                                                                            <FadeInThemeAnimation TargetName="ScrollBarSeparator" />

                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar"
                                                               Storyboard.TargetProperty="IndicatorMode"
                                                               Duration="0">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar"
                                                               Storyboard.TargetProperty="IndicatorMode"
                                                               Duration="0">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="MouseIndicator">
                                <Storyboard>
                                    <FadeInThemeAnimation TargetName="ScrollBarSeparator" />
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar"
                                                               Storyboard.TargetProperty="IndicatorMode"
                                                               Duration="0">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar"
                                                               Storyboard.TargetProperty="IndicatorMode"
                                                               Duration="0">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid Background="{TemplateBinding Background}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <ScrollContentPresenter x:Name="ScrollContentPresenter"
                                            Grid.RowSpan="2"
                                            Grid.ColumnSpan="2"
                                            ContentTemplate="{TemplateBinding ContentTemplate}"
                                            Margin="{TemplateBinding Padding}" />
                        <ScrollBar x:Name="VerticalScrollBar"
                               Grid.Column="1"
                               IsTabStop="False"
                               Maximum="{TemplateBinding ScrollableHeight}"
                               Orientation="Vertical"
                               Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
                               Value="{TemplateBinding VerticalOffset}"
                               ViewportSize="{TemplateBinding ViewportHeight}"
                               HorizontalAlignment="Right"/>
                        <ScrollBar x:Name="HorizontalScrollBar"
                               IsTabStop="False"
                               Maximum="{TemplateBinding ScrollableWidth}"
                               Orientation="Horizontal"
                               Grid.Row="1"
                               Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
                               Value="{TemplateBinding HorizontalOffset}"
                               ViewportSize="{TemplateBinding ViewportWidth}" />
                        <!-- Change the opacity below, to zero. otherwise, the right and bottom border end up showing up as a single pixel lit on the screen even if the scroll is disabled. -->
                        <Border x:Name="ScrollBarSeparator"
                            Grid.Row="1"
                            Grid.Column="1"
                            Opacity="0"
                            BorderThickness="0,0,1,1"
                            Background="{StaticResource ScrollBarTrackBackgroundThemeBrush}"
                            BorderBrush="{StaticResource ScrollBarTrackBorderThemeBrush}" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我尝试删除代码的各个部分,但结果是 ScrollBar 完全消失了。

【问题讨论】:

  • 请为您的问题添加快照。
  • 根据要求,我添加了一张图片。

标签: windows-runtime windows-8.1 windows-phone-8.1


【解决方案1】:

您为什么不直接将ScrollViewer 实例的VerticalScrollBarVisibility 和/或HorizontalScrollBarVisibility 设置为Visible,而不是从样式中移除褪色行为?

<ScrollViewer VerticalScrollBarVisibility="Visible">
     <!-- ScrollViewer Content -->
</ScrollViewer>

评论后编辑:

我想我想出了一个“解决方案”。我不确定这是否是实现这一目标的最佳方式,但它似乎可以提供您想要的结果。

ScrollViewer 创建一个自定义样式,然后为垂直/水平ScrollBar 本身创建一个样式(使用Blend,这是我之前假设您所做的)。 获得默认样式的副本后,编辑以下行:

<VisualState x:Name="NoIndicator">
    <Storyboard>
        <FadeOutThemeAnimation BeginTime="0" TargetName="HorizontalPanningRoot"/>
        <FadeOutThemeAnimation BeginTime="0" TargetName="VerticalPanningRoot"/>
        <Fade**In**ThemeAnimation BeginTime="0" TargetName="HorizontalRoot"/>
        <Fade**In**ThemeAnimation BeginTime="0" TargetName="VerticalRoot"/>
    </Storyboard>
</VisualState>

我的猜测是,这实际上会导致ScrollBar 在未与之交互时淡入,这意味着它始终可见。

这是相关的 ScrollViewer XAML(我无法在答案中包含全部内容)。请注意,ScrollViewer 设置为使用我的自定义样式ScrollViewerStyle1,然后在该样式中将VerticalScrollBar 设置为我的ScrollBar 自定义样式ScrollBarCustomStyle1,其中修改了NoIndicator VisualState。如果需要,您可以对水平滚动条执行相同操作。

ScrollViewer 样式:

<ScrollContentPresenter x:Name="ScrollContentPresenter" Grid.ColumnSpan="2" ContentTemplate="{TemplateBinding ContentTemplate}" Margin="{TemplateBinding Padding}" Grid.RowSpan="2"/>
<ScrollBar x:Name="VerticalScrollBar" Grid.Column="1" HorizontalAlignment="Right" IsTabStop="False" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{TemplateBinding VerticalOffset}" ViewportSize="{TemplateBinding ViewportHeight}" Style="{StaticResource ScrollBarStyle1}"/>
<ScrollBar x:Name="HorizontalScrollBar" IsTabStop="False" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{TemplateBinding HorizontalOffset}" ViewportSize="{TemplateBinding ViewportWidth}"/>
<Border x:Name="ScrollBarSeparator" BorderBrush="{ThemeResource ScrollBarTrackBorderThemeBrush}" BorderThickness="0,0,1,1" Background="{ThemeResource ScrollBarTrackBackgroundThemeBrush}" Grid.Column="1" Grid.Row="1"/>

【讨论】:

  • 对不起,我忘了提及我已经尝试/谷歌搜索了。它不是这样工作的:“这里有一点泄漏的抽象,其中 Visible 对 ScrollViewer 的含义与对人类读者的含义不同。将 VerticalScrollBarVisibility 设置为 Visible 时,ScrollBar 始终存在并且就 ScrollViewer 而言,“可见”。虽然在 ScrollBar 本身内,滚动条和拇指仅在处于 MouseIndicator 模式时才会绘制:如果用户没有通过鼠标与它们交互,则不会显示默认的 ScrollBar 样式。 " tinyurl.com/och8xrz
  • 已编辑答案,见上文
  • 通过使用此处的默认样式 (msdn.microsoft.com/en-us/library/windows/apps/xaml/…),我收到 4 个 ThemeBrush 和 ThemeThickness 错误(无法解析资源)。您能否提供您使用的默认样式?以前我尝试通过 Blend ScrollViewer 的状态解决淡入和淡出问题,但显然我没有安装任何东西。
  • 已更新。我还稍微更改了原始说明,因此请再次检查。
  • 我认为答案的某些部分丢失了,或者您忘记了链接。 :)
【解决方案2】:

为了达到预期的效果,你需要改变滚动条的样式,因为滚动查看器是由滚动条组成的。

工作滚动条

 <x:Double x:Key="ScrollBarMinThemeWidth">7</x:Double>
    <x:Double x:Key="ScrollBarMinThemeHeight">7</x:Double>
    <x:Double x:Key="ScrollBarPanningThumbThemeHeight">2.4</x:Double>
    <x:Double x:Key="ScrollBarPanningThumbThemeWidth">2.4</x:Double>
    <Style  TargetType="ScrollBar">
        <Setter Property="MinWidth" Value="{ThemeResource ScrollBarMinThemeWidth}"/>
        <Setter Property="MinHeight" Value="{ThemeResource ScrollBarMinThemeHeight}"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Foreground" Value="Transparent"/>
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ScrollBar">
                    <Grid x:Name="Root" Background="Red">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="PointerOver"/>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" To="0.5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="ScrollingIndicatorStates">
                                <VisualState x:Name="TouchIndicator">
                                    <!--<Storyboard>
                                        <FadeInThemeAnimation Storyboard.TargetName="HorizontalPanningRoot"/>
                                        <FadeInThemeAnimation Storyboard.TargetName="VerticalPanningRoot"/>
                                    </Storyboard>-->
                                </VisualState>
                                <VisualState x:Name="MouseIndicator"/>
                                <VisualState x:Name="NoIndicator">
                                    <!--<Storyboard>
                                        <FadeOutThemeAnimation BeginTime="0" Storyboard.TargetName="HorizontalPanningRoot"/>
                                        <FadeOutThemeAnimation BeginTime="0" Storyboard.TargetName="VerticalPanningRoot"/>
                                    </Storyboard>-->
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Grid x:Name="HorizontalPanningRoot" MinWidth="53">
                            <Rectangle x:Name="HorizontalPanningThumb" AutomationProperties.AccessibilityView="Raw" Fill="{ThemeResource ScrollBarPanningBackgroundThemeBrush}" HorizontalAlignment="Left" Height="{ThemeResource ScrollBarPanningThumbThemeHeight}" MinWidth="{ThemeResource ScrollBarMinThemeWidth}"/>
                        </Grid>
                        <Grid x:Name="VerticalPanningRoot" MinHeight="53">
                            <Rectangle x:Name="VerticalPanningThumb" AutomationProperties.AccessibilityView="Raw" Fill="{ThemeResource ScrollBarPanningBackgroundThemeBrush}" MinHeight="{ThemeResource ScrollBarMinThemeHeight}" VerticalAlignment="Top" Width="{ThemeResource ScrollBarPanningThumbThemeWidth}"/>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

<ScrollViewer Height="300" Margin="30" ScrollViewer.VerticalScrollMode="Enabled"  ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Visible">
    <TextBlock FontSize="20" TextWrapping="Wrap" Text="Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum."/>      
</ScrollViewer>

结果

【讨论】:

  • 我试过了,只有一个问题,不能点击滚动条滚动。它没有响应。有什么解决办法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-21
  • 2014-03-25
相关资源
最近更新 更多