弹出与" StaysOpen = false"抢断LeftMouseButtonDown事件

时间:2015-04-27 07:25:07

标签: c# wpf xaml popup slider

在我的应用程序中,当用户尝试单击主窗口上的滑块时,弹出控件处于打开状态时,弹出控件会窃取鼠标按下事件。 这会导致滑块无法正确响应鼠标按下事件。 (它似乎得到焦点并转移到一个不正确的位置)

我发现" OnPreviewMouseLeftButtonDown"弹出窗口中的滑块不会触发" StaysOpen"属性为false(弹出窗口打开), 并且当它的真实时(或当弹出窗口关闭时)触发。

我想知道是否有人找到了解决此问题的方法。

我在各种环境中的应用程序的其他控件中遇到了这些类型的问题,所以我更喜欢一个更通用的解决方案,而不仅仅是为滑块解决这个问题。

示例代码:

<Window x:Class="SampleApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="Root"
    Title="MainWindow" Height="350" Width="525">
<Grid Height="130" Width="300">
    <Button Width="40" Height="40" Click="ButtonBase_OnClick" HorizontalAlignment="Left" VerticalAlignment="Top"></Button>
    <Popup StaysOpen="False" IsOpen="{Binding ElementName=Root, Path=IsOpen}" Width="100" Height="100"
           HorizontalAlignment="Center" VerticalAlignment="Center" Placement="Center">
        <Grid Background="Black">
            <TextBlock Text="hello"></TextBlock>
        </Grid>
    </Popup>
    <Slider Width="200" IsMoveToPointEnabled="True" VerticalAlignment="Bottom"></Slider>
</Grid>

非常感谢, Yotam

3 个答案:

答案 0 :(得分:1)

这是因为PreviewMouseDown(及其衍生物)(来自基类UIElement)具有默认RoutingStrategy.Direct

  

直接 - 路由事件不通过元素树进行路由,但支持其他路由事件功能,如类处理,EventTrigger或EventSetter。

这是从ReferenceSource获取的事件的源代码。

public static readonly RoutedEvent PreviewMouseLeftButtonDownEvent =
    EventManager.RegisterRoutedEvent(
         "PreviewMouseLeftButtonDown",
         RoutingStrategy.Direct,
         typeof(MouseButtonEventHandler),
         _typeofThis);

以下是Popup

中发生的情况
private void OnPreviewMouseButton(MouseButtonEventArgs e)
{
    // We should only react to mouse buttons if we are in an auto close mode (where we have capture)
    if (_cacheValid[(int)CacheBits.CaptureEngaged] && !StaysOpen)
    {
        Debug.Assert( Mouse.Captured == _popupRoot.Value, "_cacheValid[(int)CacheBits.CaptureEngaged] == true but Mouse.Captured != _popupRoot");

        // If we got a mouse press/release and the mouse isn't on the popup (popup root), dismiss.
        // When captured to subtree, source will be the captured element for events outside the popup.
        if (_popupRoot.Value != null && e.OriginalSource == _popupRoot.Value)
        {
            // When we have capture we will get all mouse button up/down messages.
            // We should close if the press was outside.  The MouseButtonEventArgs don't tell whether we get this
            // message because we have capture or if it was legit, so we have to do a hit test.
            if (_popupRoot.Value.InputHitTest(e.GetPosition(_popupRoot.Value)) == null)
            {
                // The hit test didn't find any element; that means the click happened outside the popup.
                SetCurrentValueInternal(IsOpenProperty, BooleanBoxes.FalseBox);
            }
        }
    }
}

所以它被设计为以这种方式工作,你可能不会使用OnPreviewMouseDown来完成你想要在这里完成的任何事情。

答案 1 :(得分:0)

  

在我的应用程序中,当用户尝试单击主窗口上的滑块时,弹出控件打开时,弹出控件会窃取鼠标按下事件

虽然您的描述不完全正确,但这是任何Popup控件的正常行为。发生这种情况的原因是因为Popup控件具有焦点,因此它正在侦听Click事件,即使它发生在Popup 。现在从逻辑上考虑一下......如果它没有这样做,它怎么知道何时关闭?您会在Popup中使用的ComboBox控件中找到相同的行为。

答案 2 :(得分:0)

有一种解决方法可以实现您需要的行为,为您使用的Slider控件设置' IsHitTestVisible = True '。

<强> PS: 设置IsHitTestVisible = True,仅在弹出窗口打开时 - 否则为假。