我已经模仿了一个“最小”ScrollViewer
除了删除了箭头之外的所有东西:
我正在寻找一种方法来隐藏任何指定方向的箭头,此时无法进一步滚动(例如,“向上”和“向左”箭头应该在加载时隐藏)。
我以为我是子类ScrollViewer
或ScrollBar
,但这两个类都是(与WPF不同)密封的。那么如何添加这种行为呢?
答案 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>