WPF检测滚动父控件 [英] WPF detect scrolling parent Control

查看:49
本文介绍了WPF检测滚动父控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下您打开WPF Popup 的情况(例如,通过 ButtonClick )。
您直接在弹出窗口中有一个 ListBox ,其中包含一些项目,因此您必须能够滚动。
想象一下这是您的自定义控件,它位于 ScrollViewer 中。

Imagine the situation you open a WPF Popup(e.g. through ButtonClick). You have a ListBox directly in the Popup with some items, so you have to be able to scroll. Imagine that this is your Custom Control and it's located in the ScrollViewer.

现在,如果您将鼠标从 Popup 表面移到外面并滚动,会发生什么?
上下滚动,但打开 Popup !就是问题。

Now if you move with your mouse outside from the Popup surface and scroll, what happens? You scroll up and down but with the Popup opened ! And that's the problem.

问题是,如何从控件内部检测到VisualTree中其他未知的父控件已开始滚动?
并连续设置 IsDropDownOpen = false

The question is, how to detect from inside the Control, that some other unknown Parent Control in the VisualTree has started to scroll ? and consecutively set IsDropDownOpen = false?

推荐答案

可以编写触发器,以与 ScrollViewer 中包含的元素一起使用。这是一个完整的示例应用程序:

We can write a trigger for use with elements contained within a ScrollViewer. Here is a complete sample application:

<Grid>
    <ScrollViewer VerticalAlignment="Top" Height="200">
        <StackPanel HorizontalAlignment="Left">
            <Button Name="button" Content="Open">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=popup}" PropertyName="IsOpen" Value="True"/>
                    </i:EventTrigger>
                    <local:ScrollTrigger>
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=popup}" PropertyName="IsOpen" Value="False"/>
                    </local:ScrollTrigger>
                </i:Interaction.Triggers>
            </Button>
            <Popup Name="popup" PlacementTarget="{Binding ElementName=button}">
                <TextBlock Background="White" Text="Sample text"/>
            </Popup>
            <Rectangle Width="100" Height="100" Fill="Red"/>
            <Rectangle Width="100" Height="100" Fill="Green"/>
            <Rectangle Width="100" Height="100" Fill="Blue"/>
            <Rectangle Width="100" Height="100" Fill="Yellow"/>
        </StackPanel>
    </ScrollViewer>
</Grid>

我们有一个按钮可以打开弹出窗口并且在任何父 ScrollViewer 中滚动都会触发 ScrollTrigger 操作,然后我们可以关闭弹出窗口。请注意,触发器附加到 Button 而不是 Popup 。我们可以使用视觉树中的任何附近元素。还要注意,我们使用另一个触发器来打开 Popup ,但是如何打开它对于原始问题并不重要。

We have a button that opens a Popup and any scrolling in any parent ScrollViewer causes the ScrollTrigger actions to fire and then we can close the popup. Note that the trigger is attached to the Button and not the Popup. We can use any nearby element that is in the visual tree. Also note that we use another trigger to open the Popup but how it opens is not important to the original question.

这是 ScrollTrigger

class ScrollTrigger : TriggerBase<FrameworkElement>
{
    protected override void OnAttached()
    {
        AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
    }

    void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        foreach (var scrollViewer in GetScrollViewers())
            scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer_ScrollChanged);
    }

    void scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        InvokeActions(e.OriginalSource);
    }

    IEnumerable<ScrollViewer> GetScrollViewers()
    {
        for (DependencyObject element = AssociatedObject; element != null; element = VisualTreeHelper.GetParent(element))
            if (element is ScrollViewer) yield return element as ScrollViewer;
    }
}

ScrollTrigger 非常简单,它仅附加到所有父 ScrollChanged 事件并触发任何包含的动作。在示例中,我们使用 ChangePropertyAction 关闭 Popup

The ScrollTrigger is very simple, it just attaches to all parent ScrollChanged events and fires any contained actions. In the sample we use the ChangePropertyAction to close the Popup.

如果您不熟悉行为,请安装Expression Blend 4 SDK并添加以下名称空间:

If you are not familiar with behaviors, install the Expression Blend 4 SDK and add these namespaces:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

并添加 System.Windows.Interactivity Microsoft。 Expression.Interactions 到您的项目。

这篇关于WPF检测滚动父控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆