如何保持可见1秒,然后返回到wpf中的隐藏可见性



我有一个ScrollBar的样式。默认情况下,滚动条中的轨迹具有"隐藏可见性"。如果出现以下情况之一,则更改为可见:-鼠标在滚动条上-或者,用户当前正在使用滚轮滚动一旦可见性条件不再满足,如何保持轨迹可见1秒,然后返回"隐藏"?

谢谢!

 <ControlTemplate x:Key="VerticalScrollBarTemplate" TargetType="{x:Type ScrollBar}">
    <Grid Width="15">
        <Border Opacity="0.7"/>
        <Track x:Name="PART_Track" 
            Width="12"
            MinHeight="20"
            Height="Auto"
            Margin="2"
            IsDirectionReversed="true" >
            <Track.DecreaseRepeatButton>
                <RepeatButton Style="{StaticResource ScrollBackgroundStyle}" Command="ScrollBar.LineUpCommand"  />
            </Track.DecreaseRepeatButton>
            <Track.IncreaseRepeatButton>
                <RepeatButton Style="{StaticResource ScrollBackgroundStyle}" Command="ScrollBar.LineDownCommand" />
            </Track.IncreaseRepeatButton>
            <Track.Thumb>
                <Thumb Name="Thumb" Visibility="Hidden" Style="{StaticResource ScrollBarThumbStyle}" />
            </Track.Thumb>
        </Track>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
            <Setter TargetName="Thumb" Property="Visibility" Value="Visible"/>                
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

我尝试使用:

 <Storyboard x:Key="FadeInStoryboard">
    <DoubleAnimation Storyboard.TargetName="Thumb" 
             Storyboard.TargetProperty="Opacity"
             From="0" To="1"  Duration="0:0:0.5"/>
</Storyboard>
<Storyboard x:Key="FadeOutStoryboard" BeginTime="0:0:1">
        <DoubleAnimation Storyboard.TargetName="Thumb"
                 Storyboard.TargetProperty="Opacity"
                 From="1" To="0"  Duration="0:0:0.5" />
    </Storyboard>
<Trigger Property="IsMouseOver" Value="true">
                <Setter TargetName="Thumb" Property="Visibility" Value="Visible"/>
                <Trigger.EnterActions>
                    <BeginStoryboard Storyboard="{StaticResource FadeInStoryboard}" />
                </Trigger.EnterActions>
                <Trigger.ExitActions><
                    <BeginStoryboard Storyboard="{StaticResource FadeOutStoryboard}" />
                </Trigger.ExitActions>
            </Trigger>

但如果没有保留,轨迹将在1秒内可见,然后返回"隐藏",除非我在ScrollBar中设置轨迹默认为"可见性可见"。谢谢

问题是您的Setter,您将Visibility设置为Visible。一旦IsMouseOver属性的值更改为false,触发器将自动将Visibility设置回Hidden。要解决此问题,您必须设置Visibility属性的动画,并从触发器中删除Setter

故事板示例:

<Storyboard x:Key="FadeInStoryboard">
    <ObjectAnimationUsingKeyFrames Duration="0:0:0" 
                                   Storyboard.TargetName="Thumb"
                                   Storyboard.TargetProperty="Visibility">
        <DiscreteObjectKeyFrame KeyTime="0%" Value="{x:Static Visibility.Visible}"/>
    </ObjectAnimationUsingKeyFrames>
    <DoubleAnimation Duration="0:0:0.5" From="0"
                     Storyboard.TargetName="Thumb" 
                     Storyboard.TargetProperty="Opacity" To="1" />
</Storyboard>
<Storyboard x:Key="FadeOutStoryboard" >
    <DoubleAnimation Duration="0:0:0.5" From="1" BeginTime="0:0:1"
                     Storyboard.TargetName="Thumb" Storyboard.TargetProperty="Opacity"
                     To="0" />
    <ObjectAnimationUsingKeyFrames Duration="0:0:1" 
                                   Storyboard.TargetName="Thumb" 
                                   Storyboard.TargetProperty="Visibility">
        <DiscreteObjectKeyFrame KeyTime="100%" Value="{x:Static Visibility.Hidden}"/>
    </ObjectAnimationUsingKeyFrames>
</Storyboard>

编辑:这是在使用鼠标滚轮滚动时触发相同行为的一种可能方式。我只是很快创建了这个,所以在使用它之前请检查它,并期望它是健壮的。您必须创建一个新类并从ScrollViewer:派生它

public class ScrollViewerEx : ScrollViewer {
    public static readonly DependencyProperty IsScrollingWithMouseWheelProperty = DependencyProperty.Register(
        "IsScrollingWithMouseWheel", typeof (bool), typeof (ScrollViewerEx), new FrameworkPropertyMetadata(false));
    public bool IsScrollingWithMouseWheel {
        get { return (bool) GetValue(IsScrollingWithMouseWheelProperty); }
        set { SetValue(IsScrollingWithMouseWheelProperty, value); }
    }
    private readonly DispatcherTimer mouseWheelActivityTimer;
    public ScrollViewerEx() {
        mouseWheelActivityTimer = new DispatcherTimer();
        mouseWheelActivityTimer.Interval = TimeSpan.FromSeconds(1);
        mouseWheelActivityTimer.Tick += MouseWheelActivityTimerOnTick;
    }
    private void MouseWheelActivityTimerOnTick(object sender, EventArgs eventArgs) {
        mouseWheelActivityTimer.Stop();
        IsScrollingWithMouseWheel = false;
    }
    protected override void OnMouseWheel(MouseWheelEventArgs e) {
        mouseWheelActivityTimer.Stop();
        IsScrollingWithMouseWheel = true;
        mouseWheelActivityTimer.Start();
        base.OnMouseWheel(e);
    }
}

将以下DataTrigger添加到ScrollBarControlTemplate注意:这会显式停止BeginStoryboard s,您还需要将StopStoryboard s添加到ControlTemplate中现有的Trigger中,否则最后一个Trigger将阻塞第一个Trigger

<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=data:ScrollViewerEx}, Path=IsScrollingWithMouseWheel}" 
             Value="True">
    <DataTrigger.EnterActions>
        <StopStoryboard BeginStoryboardName="fadeOut"/>
        <BeginStoryboard Storyboard="{StaticResource FadeInStoryboard}" Name="fadeIn"/>
    </DataTrigger.EnterActions>
    <DataTrigger.ExitActions>
        <StopStoryboard BeginStoryboardName="fadeIn"/>
        <BeginStoryboard Storyboard="{StaticResource FadeOutStoryboard}" Name="fadeOut"/>
    </DataTrigger.ExitActions>
</DataTrigger>

编辑2:这是另一种方法,使用附加的属性和EventTrigger

您必须调整ScrollViewerControlTemplate以添加以下EventTrigger:

<EventTrigger RoutedEvent="PreviewMouseWheel">
    <BeginStoryboard>
        <Storyboard FillBehavior="Stop">
            <BooleanAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetProperty="(data:ScrollViewerProperties.IsScrollingWithMouseWheel)">
                <DiscreteBooleanKeyFrame KeyTime="0%" Value="True"/>
            </BooleanAnimationUsingKeyFrames>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>

并创建一个类来定义中的附加属性,类似于以下内容:

public static class ScrollViewerProperties {
    public static readonly DependencyProperty IsScrollingWithMouseWheelProperty = DependencyProperty.RegisterAttached(
        "IsScrollingWithMouseWheel", typeof (bool), typeof (ScrollViewerProperties), new PropertyMetadata(default(bool)));
    public static void SetIsScrollingWithMouseWheel(DependencyObject element, bool value) {
        element.SetValue(IsScrollingWithMouseWheelProperty, value);
    }
    public static bool GetIsScrollingWithMouseWheel(DependencyObject element) {
        return (bool) element.GetValue(IsScrollingWithMouseWheelProperty);
    }
}

并更新ScrollBar模板中的DataTrigger以使用附加的属性,如下所示:

<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}},Path=(data:ScrollViewerProperties.IsScrollingWithMouseWheel)}" Value="True">
    <DataTrigger.EnterActions>
        <StopStoryboard BeginStoryboardName="fadeOut"/>
        <BeginStoryboard Storyboard="{StaticResource FadeInStoryboard}" Name="fadeIn"/>
    </DataTrigger.EnterActions>
    <DataTrigger.ExitActions>
        <StopStoryboard BeginStoryboardName="fadeIn"/>
        <BeginStoryboard Storyboard="{StaticResource FadeOutStoryboard}" Name="fadeOut"/>
    </DataTrigger.ExitActions>
</DataTrigger>

只是为了完成一个精彩的@Roel van Westerop评论。我自己尝试过编辑2。除了一件小事,它的效果很好。与其只使用DataTrigger,不如使用这样的MultiDataTrigger:

<MultiDataTrigger>
     <MultiDataTrigger.Conditions>
           <Condition Binding="{Binding RelativeSource=
                      {RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}},
                       Path=(data:ScrollViewerProperties.IsScrollingWithMouseWheel)}" Value="True"/>
           <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self},
                                        Path=IsMouseOver}" Value="False"/>                                
     </MultiDataTrigger.Conditions>
     <MultiDataTrigger.EnterActions>
          <StopStoryboard BeginStoryboardName="fadeOut"/>
          <BeginStoryboard Storyboard="
                                {StaticResource FadeInStoryboard}" Name="fadeIn"/>
      </MultiDataTrigger.EnterActions>
      <MultiDataTrigger.ExitActions>
           <StopStoryboard BeginStoryboardName="fadeIn"/>
           <BeginStoryboard Storyboard="{StaticResource FadeInStoryboard}" Name="fadeOut"/>
      </MultiDataTrigger.ExitActions>
</MultiDataTrigger>

此MultiDataTrigger修复了当您将鼠标悬停在滚动条上并使用MouseWheel滚动内容时的错误(如果没有此multitrigger,即使鼠标悬停在其上,滚动条也会淡出)

最新更新