0

Sorry in advance if the title is confusing. Here's the situation. I have a grid called grdFilters. This grid has a series of CheckBoxes within it (one per row). Normally this grid is hidden. But I wanted it to show up when prompted (on button click) and leave when the user clicks somewhere other than the grid. To handle outside control mouse clicks I tried first capturing the mouse as such:

    AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl));

    private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
    {
        if (this.filters) //Check if the Filters grid is visible
        {
            ShowHideMenu("sbHideFilters", grdFilters); //Method that hides the grid
            Mouse.Capture(null); //Release the mouse
        }
    }

    private void btnFilters_Click(object sender, RoutedEventArgs e)
    {
        if (!this.filters) //Check if the filters grid is shown
        {
            ShowHideMenu("sbShowFilters", grdFilters); //Method that reveals the grid
            Mouse.Capture(grdFilters); //Capture the mouse
        }
    }

The problem is that while the Filters grid has captured the mouse, none of the grids children (the Check Boxes) can be clicked on. I would really like to find a way to detect when the mouse is clicked outside of the grid while still allowing the children of the grid to accept mouse down events. Any help would be greatly appreciated, thanks in advance.

As per request here is some of my Xaml:

<Grid>
    <Label x:Name="label" Content="Events" HorizontalAlignment="Center" VerticalAlignment="Top"/>
    <ScrollViewer HorizontalAlignment="Left" Height="619" Margin="0,26,0,0" VerticalAlignment="Top" Width="450" VerticalScrollBarVisibility="Hidden">
        <Grid x:Name="Schedule" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="450" Margin="10,0,0,0"/>
    </ScrollViewer>
    <Grid x:Name="grdFilters" HorizontalAlignment="Left" Height="619" Margin="490,26,-176,0" VerticalAlignment="Top" Width="135" Background="{StaticResource TransparentBackground}" Panel.ZIndex="95">
        <CheckBox x:Name="chckAll" Content="All" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top" Checked="chckAll_Checked" Unchecked="chckAll_Unchecked"/>
        <Grid x:Name="grdFilters" HorizontalAlignment="Left" Height="588" Margin="0,31,0,0" VerticalAlignment="Top" Width="136"/>
    </Grid>
    <Button x:Name="btnFilters" Content="" Margin="436,223,-18,0" VerticalAlignment="Top" Background="Cyan" Opacity="0.15" Style="{StaticResource MyTabStyle}" Height="80" Click="btnFilters_Click"/>

</Grid>

The only thing I left out were the Resource Dictionaries and the page definition itself.

4

1 回答 1

1

我认为Mouse.Captureand PreviewMouseDownOutsideCapturedElementEventand 对你想要的来说太具体了。

我宁愿使用 a hitResultsList,它可以在很多不同的场景中使用:

我稍微修改了 ehAddHandler

AddHandler(Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler(HandleMouseDown));

我添加了VisualTreeHelper.HitTest逻辑

    //List to store all the elements under the cursor
    private List<DependencyObject> hitResultsList = new List<DependencyObject>();

    private void HandleMouseDown(object sender, MouseButtonEventArgs e)
    {

        Point pt = e.GetPosition((UIElement)sender);
        hitResultsList.Clear();

        //Retrieving all the elements under the cursor
        VisualTreeHelper.HitTest(this, null,
            new HitTestResultCallback(MyHitTestResult),
            new PointHitTestParameters(pt));

        //Testing if the grdFilters is under the cursor
        if (!hitResultsList.Contains(this.grdFilters) && grdFilters.Visibility == System.Windows.Visibility.Visible)
        {
            grdFilters.Visibility = System.Windows.Visibility.Hidden;
        }
    }

    //Necessary callback function
    private HitTestResultBehavior MyHitTestResult(HitTestResult result)
    {
        hitResultsList.Add(result.VisualHit);
        return HitTestResultBehavior.Continue;
    }

这样你也可以Mouse.Capture从 btnFilters_Click 中删除调用:

    private void btnFilters_Click(object sender, RoutedEventArgs e)
    {
        if (grdFilters.Visibility != System.Windows.Visibility.Visible)
            grdFilters.Visibility = System.Windows.Visibility.Visible; }
    }
于 2018-10-31T04:17:26.850 回答