如何在wpf中实现基于滚动的触发器?

时间:2015-08-28 07:49:30

标签: wpf xaml

尝试做一些基于滚动的触发器,如何根据滚动位置(顶部,中间,底部,值)实现自定义routedevent触发器raise / fire

with top,当元素进入顶部滚动视图

底部,当元素进入底部滚动视图

中,进入中间滚动视图

值,达到特定的滚动位置

我的目的是为wpf

模仿一些基于滚动的触发动画

3 个答案:

答案 0 :(得分:0)

我看到了三个解决方案:

  1. 自定义触发器(来自System.Windows.Interactivity)
  2. 自定义附加活动
  3. 在代码隐藏中附加到ScrollViewer.ScrollChanged事件并从那里播放动画(动画仍然可以在xaml中定义)
  4. 1。使用自定义触发器

    的解决方案
    public class ScrollEventTrigger  : System.Windows.Interactivity.EventTrigger
    {
        public ScrollUnit Unit { get; set; }
    
        public double VerticalOffset { get; set; }
    
    
        protected override string GetEventName()
        {
            return "ScrollChanged";
        }
    
        protected override void OnEvent(EventArgs eventArgs)
        {
            var args = (ScrollChangedEventArgs)eventArgs;
            var scrollViewer = (ScrollViewer)args.Source;
    
            var verticalOffsetAbs = VerticalOffset;
            if (Unit == ScrollUnit.Relative)
            {
                verticalOffsetAbs = VerticalOffset*scrollViewer.ViewportWidth;
            }
    
            //you have to play more with this condition, because you may scroll directly from 0.4 to 0.6 and the 0.5 can be skipped.
            if (args.VerticalOffset == verticalOffsetAbs)
            {
                base.OnEvent(eventArgs);
            }
        }
    }
    
    @EventHandler
    public void onPlayerInteractEntity(PlayerInteractEntityEvent e) {
        Player p = e.getPlayer();
        if(plugin.spectating.contains(p)) {
            if(e.getRightClicked() instanceof Player) {
                Player target = (Player) e.getRightClicked();
                if(plugin.alive.contains(target)) {
                    target.setPassenger(p);
                }
            }
        }
    }
    

答案 1 :(得分:0)

我看到了三个解决方案:

  1. 自定义触发器(来自System.Windows.Interactivity)
  2. 自定义附加活动
  3. 在代码隐藏中附加到ScrollViewer.ScrollChanged事件并从那里播放动画(动画仍然可以在xaml中定义)
  4. 2。使用自定义附加事件的解决方案

    这种方法的优点是,您可以在控件样式中轻松使用它。 缺点是,当必须触发事件时,您无法配置准确的位置,并且必须进行硬编码。

    <ScrollViewer x:Name="ScrollViewer1">
        <ScrollViewer.Triggers>
            <EventTrigger RoutedEvent="my:ScrollViewerExtension.ScrolledTop">
                <BeginStoryboard Storyboard="{StaticResource ScrolledTopAnimations}" />
            </EventTrigger>
            <EventTrigger RoutedEvent="my:ScrollViewerExtension.ScrolledToMiddle">
                <BeginStoryboard Storyboard="{StaticResource ScrolledToMiddleAnimations}" />
            </EventTrigger>
         </ScrollViewer.Triggers>
    
    
    </ScrollViewer>
    
    public static class ScrollViewerExtension
    {
        public static readonly RoutedEvent ScrolledTopEvent = EventManager.RegisterRoutedEvent("ScrolledTop", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ScrollViewerExtension));
        public static void AddScrolledTopHandler(DependencyObject d, RoutedEventHandler handler)
        {
            ((UIElement) d).AddHandler(ScrolledTopEvent, handler);
    
            var scrollViewer = (ScrollViewer) d;
    
            scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged; //to avoid multiple subscription
            scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
        }
    
        public static void RemoveScrolledTopHandler(DependencyObject d, RoutedEventHandler handler)
        {
            ((UIElement)d).RemoveHandler(ScrolledTopEvent, handler);
        }
    
        static void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (e.VerticalOffset == 0)
            {
                ((UIElement)sender).RaiseEvent(new RoutedEventArgs(ScrolledTopEvent, sender));
            }
            //else if... trigger other events
            //else if 
        }
    }
    

答案 2 :(得分:0)

我看到了三个解决方案:

  1. 自定义触发器(来自System.Windows.Interactivity)
  2. 自定义附加活动
  3. 在代码隐藏中附加到ScrollViewer.ScrollChanged事件并从那里播放动画(动画仍然可以在xaml中定义)
  4. 3。使用

    后面的代码解决方案

    当然,我们不能忘记使用代码背后的最简单的解决方案。只需比较其他解决方案所需的代码数量:

    void ScrollViewer1_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (e.VerticalOffset == 0)
        {
            ((Storyboard)FindResource("ScrolledTopAnimations")).Begin();
        }
        //else if... trigger other animations
        //else if 
    }