如何防止ScrollViewer处理后代的MouseMove事件? (适用于Windows Phone的Silverlight)

时间:2013-02-21 00:08:40

标签: silverlight scrollviewer mousemove event-bubbling

考虑一下:

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

  <MyControl MouseMove="myMouseMoveHandler" />

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

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

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

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

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

必须可以阻止ScrollViewer获取MouseMove。证明:只需将ListCon替换为包含更多项目的ListBox,而不是适合其高度,您可以在不对ScrollViewer做出反应的情况下滑动ListBox项目。

但是怎么样?它是否也是ListBox中的ScrollViewer,这就是它在那里工作的原因,还是可以为我的控件完成?

1 个答案:

答案 0 :(得分: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事件。

此方法存在一些限制,因为禁用ScrollViewers会导致他们跳转到他们(和他们孩子的)未注册状态。所以我将MyControl置于顶部并相应地设置所有对齐。