我正在做一些实验,我正在尝试收集放在鼠标指针下的所有元素。
XAML测试代码
<StackPanel>
<Button
x:Name="HitButton"
Content="Test Button" />
<Button
x:Name="NotHitButton"
IsHitTestVisible="False"
Content="Test Button" />
</StackPanel>
要获取鼠标指针的坐标,请使用PointerMoved
:
CoreWindow.GetForCurrentThread().PointerMoved += OnPointerMoved;
private void OnPointerMoved(CoreWindow sender, PointerEventArgs args)
{
Point point = args.CurrentPoint.Position;
IEnumerable<UIElement> elements = VisualTreeHelper.FindElementsInHostCoordinates(point, null, true);
...
}
但是,当控件的属性IsHitTestVisible
设置为false
时,此方法有效,即使我设置了第三个参数FindElementsInHostCoordinates
,includeAllElements
也不会考虑它这种方法对true
。
根据documentation我希望如果我将参数includeAllElements
设置为true
,它应该找到所有元素,包括IsHitTestVisible
设置为{的那些控件{1}}。
includeAllElements [System.Boolean]
如果包含所有元素,则为true 相交,包括那些被认为是不可见的元素 测试。 false仅查找可见的,可命中的元素。该 默认为false。
我是否理解false
如何运作的错误方式?如果是这样,即使他们将FindElementsInHostCoordinates
设置为IsHitTestVisible
,还有其他方法可以检索特定坐标处的所有控件吗?
答案 0 :(得分:1)
@ZORRO的观察结果大多正确。
XAML命中测试基于如下理念:如果元素占据屏幕上的空间并且&#34; 生成墨迹 &#34;然后它进行了测试。
主要问题是围绕什么产生墨水:
对于Brush
(绝大多数)的元素,任何非空画笔都被视为生成墨迹的内容,即使画笔不会产生可见像素。例如 a SolidColorBrush
,颜色为&#34;透明&#34; 仍会生成墨迹 。 只有空画笔不会产生墨迹。
有一些特殊元素,例如SwapChainPanel
和MediaElement
没有画笔,但 仍然可以生成墨迹 强>
此处不考虑不透明度属性
因此只要上述之一为真,即使Opacity等于0,元素仍会产生墨水。
这一切意味着当includeAllElements
参数设置为true时,不会产生墨水的元素会被视为进行点击测试。在这种情况下,只要元素满足空间要求(点/矩形与元素边界相交),那么它及其祖先就会包含在结果中。
顺便说一句,我们正在与内容团队合作,以完善此文档,以便明确。
答案 1 :(得分:0)
我认为这个问题的关键点是什么是“被认为是不可见才能进行测试”。
我认为当我们将IsHitTestVisible
设置为false
时,该元素不会被视为不可见,它只是不可见。根据{{3}},元素符合以下条件是可以测试的。
- 元素的可见性属性值为可见。
- 元素的背景或填充属性值不为空。 null Brush 值会导致透明度和命中测试不可见性。 (要使元素透明但也可以测试,请使用透明画笔而不是 null 。)
- 如果元素是控件,则其 IsEnabled 属性值必须为 true 。
- 元素在布局中必须具有实际尺寸。 ActualHeight 和 ActualWidth 为0的元素不会触发输入事件。
所以我认为当元素的Visibility
属性值为Collapsed
或其Background
或Fill
属性值为null
或其IsEnabled
时属性值为false
,该元素被视为不可见。我做了一个简单的测试。
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Border Name="Border" Width="200" Height="300" BorderThickness="1" BorderBrush="Black" Background="AliceBlue">
<Grid Name="Grid" Width="100" Height="250">
<Rectangle Name="CollapsedRectangle" Fill="Azure" Visibility="Collapsed" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Rectangle Name="NoFillRectangle" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,100,0,0" />
<Button Name="Button" IsEnabled="False" VerticalAlignment="Top" Margin="0,200,0,0">CLICK</Button>
</Grid>
</Border>
</Grid>
public MainPage()
{
this.InitializeComponent();
CoreWindow.GetForCurrentThread().PointerMoved += (s, e) =>
{
Point point = e.CurrentPoint.Position;
IEnumerable<UIElement> elements = VisualTreeHelper.FindElementsInHostCoordinates(point, Border, false);
foreach (var item in elements)
{
FrameworkElement feItem = item as FrameworkElement;
System.Diagnostics.Debug.WriteLine(feItem.Name);
}
System.Diagnostics.Debug.WriteLine("-----------------------------------------");
};
}
当includeAllElements
参数设置为false
时,输出类似于
Border
-----------------------------------------
Border
-----------------------------------------
Border
-----------------------------------------
当includeAllElements
参数设置为true
时,输出就像
Border
-----------------------------------------
Grid
Border
-----------------------------------------
...
NoFillRectangle
Grid
Border
-----------------------------------------
...
Grid
Border
-----------------------------------------
Border
-----------------------------------------
因此,includeAllElements
参数似乎仅在元素的Background
或Fill
属性值为null
时生效。不确定这是否符合设计要求。 可能只有Background
或Fill
属性值为null
的元素才被视为不可见。