当没有任何内容可以滚动时,让ScrollViewer上/下箭头消失

时间:2013-12-19 22:19:11

标签: c# silverlight xaml windows-phone scrollviewer

我已经模仿了一个“最小”ScrollViewer除了删除了箭头之外的所有东西:

Templated ScrollViewer

我正在寻找一种方法来隐藏任何指定方向的箭头,此时无法进一步滚动(例如,“向上”和“向左”箭头应该在加载时隐藏)。

我以为我是子类ScrollViewerScrollBar,但这两个类都是(与WPF不同)密封的。那么如何添加这种行为呢?

1 个答案:

答案 0 :(得分:0)

我创建了一个Behavior<ScrollBar>,其中包含滚动量的依赖项属性。我将行为应用于ScrollViewer控件模板内的ScrollBars,并将HorizontalOffset / VerticalOffset属性绑定到行为的DP。然后,我向ScrollBar的控件模板添加了一些视觉状态。然后,当滚动偏移改变时,该行为负责更新视觉状态。

这是行为(实际上需要2个额外的依赖属性来完成计算:视口的大小和滚动条的范围):

public enum ScrollBarDirection { Vertical, Horizontal } ;

public class HideScrollButtonsBehavior : Behavior<ScrollBar>
{
    public ScrollBarDirection Direction { get; set; }

    public double VerticalScrollAmount
    {
        get { return (double)GetValue(VerticalScrollAmountProperty); }
        set { SetValue(VerticalScrollAmountProperty, value); }
    }
    public static readonly DependencyProperty VerticalScrollAmountProperty =
        DependencyProperty.Register("VerticalScrollAmount", typeof(double), typeof(HideScrollButtonsBehavior), new PropertyMetadata(ScrollChanged));

    public double ScrollExtent
    {
        get { return (double)GetValue(ScrollExtentProperty); }
        set { SetValue(ScrollExtentProperty, value); }
    }
    public static readonly DependencyProperty ScrollExtentProperty =
        DependencyProperty.Register("ScrollExtent", typeof(double), typeof(HideScrollButtonsBehavior), new PropertyMetadata(null));

    public double ViewportExtent
    {
        get { return (double)GetValue(ViewportExtentProperty); }
        set { SetValue(ViewportExtentProperty, value); }
    }
    public static readonly DependencyProperty ViewportExtentProperty =
        DependencyProperty.Register("ViewportExtent", typeof(double), typeof(HideScrollButtonsBehavior), new PropertyMetadata(null));

    public static void ScrollChanged(object sender, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue as double? == null)
            return;

        var owner = (HideScrollButtonsBehavior)sender;
        ScrollBar scrollBar = owner.AssociatedObject;
        double scrollPosition = (double)args.NewValue;

        if (scrollPosition <= 0)
            VisualStateManager.GoToState(scrollBar, owner.Direction + "DownOnly", true);
        else if (scrollPosition >= owner.ScrollExtent - owner.ViewportExtent)
            VisualStateManager.GoToState(scrollBar, owner.Direction + "UpOnly", true);
        else
            VisualStateManager.GoToState(scrollBar, owner.Direction + "Both", true);
    }
}

这些应用于ScrollBar控件模板中的ScrollViewer实例,就像这样(使用RelativeSource绑定设置的DP):

<ScrollBar x:Name="VerticalScrollBar" 
            IsTabStop="False"
            Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
            Orientation="Vertical"
            ViewportSize="{TemplateBinding ViewportHeight}"
            Maximum="{TemplateBinding ScrollableHeight}"
            Minimum="0" 
            Value="{TemplateBinding VerticalOffset}">
    <i:Interaction.Behaviors>
        <behavior:HideScrollButtonsBehavior 
            VerticalScrollAmount="{Binding RelativeSource={RelativeSource AncestorType=ScrollViewer},Path=VerticalOffset}" 
            ScrollExtent="{Binding RelativeSource={RelativeSource AncestorType=ScrollViewer},Path=ExtentHeight}"
            ViewportExtent="{Binding RelativeSource={RelativeSource AncestorType=ScrollViewer},Path=ViewportHeight}"
            Direction="Vertical"
            />
    </i:Interaction.Behaviors>
</ScrollBar>

最后,ScrollBar控制模板中的视觉状态只是根据需要显示/隐藏增加/减少按钮:

<VisualStateGroup x:Name="VerticalScrollButtonVisibilityStates">
    <VisualState x:Name="VerticalDownOnly">
        <Storyboard Duration="0:0:0.1">
            <DoubleAnimation Storyboard.TargetName="VerticalSmallDecrease" Storyboard.TargetProperty="Opacity"
                To="0" Duration="0:0:0.1" />
            <DoubleAnimation Storyboard.TargetName="VerticalSmallIncrease" Storyboard.TargetProperty="Opacity"
                To="1" Duration="0:0:0.1" />
        </Storyboard>
    </VisualState>
    <VisualState x:Name="VerticalUpOnly">
        <Storyboard Duration="0:0:0.1">
            <DoubleAnimation Storyboard.TargetName="VerticalSmallDecrease" Storyboard.TargetProperty="Opacity"
                To="1" Duration="0:0:0.1" />
            <DoubleAnimation Storyboard.TargetName="VerticalSmallIncrease" Storyboard.TargetProperty="Opacity"
                To="0" Duration="0:0:0.1" />
        </Storyboard>
    </VisualState>
    <VisualState x:Name="VerticalBoth">
        <Storyboard Duration="0:0:0.1">
            <DoubleAnimation Storyboard.TargetName="VerticalSmallDecrease" Storyboard.TargetProperty="Opacity"
                To="1" Duration="0:0:0.1" />
            <DoubleAnimation Storyboard.TargetName="VerticalSmallIncrease" Storyboard.TargetProperty="Opacity"
                To="1" Duration="0:0:0.1" />
        </Storyboard>
    </VisualState>
</VisualStateGroup>