UWP:如何让Border实现点击屏蔽,阻止下层UI交互?
如何让Border覆盖层阻止后方UI的交互穿透?
我需要一个覆盖层控件,通过Border阻止页面中其后方所有UI的交互。尝试了以下操作后,仍能点击穿透Border触发后方Button的命令:
- 将Border的
ManipulationMode设为None,同时设置IsTapEnabled、IsRightTapEnabled、IsDoubleTapEnabled及IsHitTestVisible为False - 订阅
Tapped和PointerEntered事件,并将事件参数的Handled属性设为true
截图参考
相关代码
DialogShell的XAML代码
<UserControl x:Class="PocMvvmToolkitApp.Dialogs.DialogShell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="overlayGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <!--dialogShield 是用于阻止点击穿透的Border--> <Border x:Name="dialogShield" Background="#AAFFFFFF" IsHitTestVisible="False" ManipulationMode="None" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" IsTapEnabled="False"/> <Border x:Name="dialogBorder" BorderBrush="Black" BorderThickness="1" /> </Grid>
事件处理代码
public DialogShell() { this.InitializeComponent(); this.allDialogs = new List<ExtendedContentDialog>(); this.visibleDialogs = new List<ExtendedContentDialog>(); // 无效 this.dialogShield.PointerEntered += this.OnModalShieldPointerEntered; this.dialogShield.Tapped += this.OnModalShieldTapped; } private void OnModalShieldTapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) { // 无法阻止点击穿透 e.Handled = true; } private void OnModalShieldPointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) { e.Handled = true; }
Page中添加/移除DialogShell的代码
private void OnDialogStackChanged(Args.DialogStackChangedEventArgs args) { switch (args.Context) { case Args.DialogStackChangedContext.Showing: if (this.dialogShell == null) { this.dialogShell = new DialogShell(); this.dialogShell.ShowDialog(args.Dialog); this.rootGrid.Children.Add(this.dialogShell); Grid.SetColumnSpan(this.dialogShell, 2); } break; case Args.DialogStackChangedContext.Closing: if (this.dialogShell != null) { this.dialogShell.RemoveDialog(args.Dialog); if (this.dialogShell.AllDialogs.Count == 0) { this.rootGrid.Children.Remove(this.dialogShell); this.dialogShell = null; } } break; } }
解决方法
问题核心是**IsHitTestVisible="False"设置错误**——该属性设为False时,控件会完全跳过命中测试,点击会直接穿透到下层控件。正确修改步骤:
- 移除
dialogShield的IsHitTestVisible="False",保持默认的True(无需显式设置) - 保留
ManipulationMode="None"和所有Is*Enabled="False"的设置,确保Border不响应任何交互动作 - 无需订阅
Tapped或PointerEntered事件,只要Border参与命中测试,就会自动阻挡下层控件的交互
修改后的dialogShield代码:
<Border x:Name="dialogShield" Background="#AAFFFFFF" ManipulationMode="None" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" IsTapEnabled="False"/>
原理说明
IsHitTestVisible="True"让Border成为点击事件的接收目标,阻挡下层控件获取事件- 各种
Is*Enabled="False"确保Border自身不响应任何交互操作,仅起到阻挡作用 ManipulationMode="None"避免Border处理手势操作,防止干扰覆盖层功能
另外需确保DialogShell在rootGrid的子控件列表中处于最后一位(即最顶层),避免被其他控件遮挡。
内容的提问来源于stack exchange,提问作者Libertarian Developer
相关产品推荐
相关产品推荐

