【问题标题】:How to prevent a ScrollViewer from handling MouseMove event of a descendant? (Silverlight for Windows Phone)如何防止 ScrollViewer 处理后代的 MouseMove 事件? (适用于 Windows Phone 的 Silverlight)
【发布时间】:2013-02-21 00:08:39
【问题描述】:

考虑一下:

<ScrollViewer>
  <!-- Several Controls /-->

  <MyControl MouseMove="myMouseMoveHandler" />

  <!-- Several Controls /-->
</ScrollViewer>

MyControl 是一个 HSV 颜色选择控件,其色谱位于可旋转的圆圈上,所选色调的细微差别位于三角形上。它看起来很棒,但遗憾的是我还不能发布图片(代表)。它确实需要能够处理其表面上所有方向的鼠标移动。

现在,当我在 MyControl 上移动鼠标(并且它正确处理移动)时,ScrollViewer 仍然滚动!

即使它是 ScrollViewer 中的唯一控件,移动在我的控件内开始和结束,和/或我在 MouseLeftButtonDown / -Up 事件中都设置了 e.Handled = true 也会发生这种情况。在 ..Down 中使用 CaptureMouse(),在 ..Up 中使用 ReleaseMouseCapture() 也无济于事。

您会同意我不能更改 ScrollViewer 实现(或者我可以吗?),并且我不能保证我的控件永远不会托管在 ScrollViewer 中(例如,因为我想发布它)。

必须可以防止 ScrollViewer 获取 MouseMove。证明:只需将 MyControl 替换为包含超过其高度的项目的 ListBox,您可以在没有 ScrollViewer 反应的情况下滑动 ListBox 项目。

但是怎么做呢?它也是 ListBox 内的一个 ScrollViewer,这就是它在那里工作的原因,或者它也可以为我的控件完成?

【问题讨论】:

    标签: silverlight scrollviewer mousemove event-bubbling


    【解决方案1】:

    好的,我找到了一个很好的解决方案。

    我的想法是如此固定在 e.Handled(在 MouseMove 中不可用)、IsHitTestVisible(也将所有孩子从触摸事件中隐藏)和诸如此类的东西上,我没有看到明显的东西。

    如果有人有同样的问题,这里是代码:

    struct ScrollVisibilities
    {
        public ScrollBarVisibility Horizontal;
        public ScrollBarVisibility Vertical;
    }
    
    Dictionary<ScrollViewer, ScrollVisibilities> scrollersStates = new Dictionary<ScrollViewer, ScrollVisibilities>();
    
    bool scrollersDisabled;
    
    void disableScrollViewers(bool disable)
    {
        if (scrollersDisabled == disable)   // can't disable if disabled or enable if enabled
            return;
        scrollersDisabled = disable;
    
        if (disable)
        {
            DependencyObject dpo = Parent;
            while (dpo is FrameworkElement)
            {
                if (dpo is ScrollViewer)
                {
                    ScrollViewer s = dpo as ScrollViewer;
                    ScrollVisibilities v = new ScrollVisibilities()
                    {
                        Horizontal = s.HorizontalScrollBarVisibility,
                        Vertical = s.VerticalScrollBarVisibility
                    };
                    scrollersStates.Add(s, v);
                    s.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
                    s.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
                }
                dpo = ((FrameworkElement)dpo).Parent;
            }
        }
        else // restore
        {
            foreach (ScrollViewer s in scrollersStates.Keys)
            {
                s.HorizontalScrollBarVisibility = scrollersStates[s].Horizontal;
                s.VerticalScrollBarVisibility = scrollersStates[s].Vertical;
            }
            scrollersStates.Clear();
        }
    }
    

    在 MouseLeftButtonDown 中,我禁用 ScrollViewers(true),并连接到 Touch.FrameReported。 在 Touch_FrameReported 中,当所有接触点都具有 Action == Up 时,我禁用 ScrollViewers(false)。这样,即使它发生在 MyControl 之外,我也会收到 Up 事件。

    这种方法有一些限制,因为禁用 ScrollViewer 会导致它们跳转到它们(和它们的子级)未滚动状态。所以我把 MyControl 放在最上面,并相应地设置所有的对齐方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多