如何让网格捕获鼠标,但仍允许它 Children 处理点击事件
How To Let A Grid Capture The Mouse, But Still Allow It's Children To Handle Click Events
如果标题令人困惑,请提前致歉。情况是这样的。我有一个名为 grdFilters
的网格。此网格中有一系列 CheckBoxes
(每行一个)。通常这个网格是隐藏的。但我希望它在出现提示时(单击按钮时)出现,并在用户单击网格以外的其他地方时离开。为了处理外部控制鼠标点击,我首先尝试捕获鼠标:
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
}
}
问题是,虽然过滤器网格捕获了鼠标,但 none 个网格 children(复选框)可以单击。我真的很想找到一种方法来检测何时在网格外单击鼠标,同时仍然允许网格的 children 接受鼠标按下事件。任何帮助将不胜感激,提前致谢。
根据要求,这是我的一些 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>
我唯一遗漏的是资源字典和页面定义本身。
我认为 Mouse.Capture
和 PreviewMouseDownOutsideCapturedElementEvent
对于您想要的内容来说太具体了。
我宁愿使用一个hitResultsList
,它可以在很多不同的场景中使用:
我稍微修改了一下诶AddHandler
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;
}
这样你也可以从 btnFilters_Click:
中删除 Mouse.Capture
调用
private void btnFilters_Click(object sender, RoutedEventArgs e)
{
if (grdFilters.Visibility != System.Windows.Visibility.Visible)
grdFilters.Visibility = System.Windows.Visibility.Visible; }
}
如果标题令人困惑,请提前致歉。情况是这样的。我有一个名为 grdFilters
的网格。此网格中有一系列 CheckBoxes
(每行一个)。通常这个网格是隐藏的。但我希望它在出现提示时(单击按钮时)出现,并在用户单击网格以外的其他地方时离开。为了处理外部控制鼠标点击,我首先尝试捕获鼠标:
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
}
}
问题是,虽然过滤器网格捕获了鼠标,但 none 个网格 children(复选框)可以单击。我真的很想找到一种方法来检测何时在网格外单击鼠标,同时仍然允许网格的 children 接受鼠标按下事件。任何帮助将不胜感激,提前致谢。
根据要求,这是我的一些 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>
我唯一遗漏的是资源字典和页面定义本身。
我认为 Mouse.Capture
和 PreviewMouseDownOutsideCapturedElementEvent
对于您想要的内容来说太具体了。
我宁愿使用一个hitResultsList
,它可以在很多不同的场景中使用:
我稍微修改了一下诶AddHandler
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;
}
这样你也可以从 btnFilters_Click:
中删除Mouse.Capture
调用
private void btnFilters_Click(object sender, RoutedEventArgs e)
{
if (grdFilters.Visibility != System.Windows.Visibility.Visible)
grdFilters.Visibility = System.Windows.Visibility.Visible; }
}