在 Popup 控件中的任意位置点击时文本框不会失去焦点
Textbox not losing focus when tapping anywhere inside Popup control
我有一个带有文本框和按钮控件的弹出窗口。
当我 click/tap 在 Popup 中的任何地方时,Textbox 不会失去焦点。
使文本框失去焦点的唯一方法是将焦点设置在按钮上。
我希望能够在不关闭弹出窗口或单击按钮的情况下从文本框中移除焦点。
此问题仅发生在 Popup 中。
我曾经将控件放在 Flyout 中,当用户在文本框外和 Flyout 内的任何地方单击时,文本框就会失去焦点。此外,当 Flyout 打开时,Textbox 会自动将焦点放在 Flyout 打开上。
我测试了文本框如何在新的空白 UWP 项目中失去焦点的不同行为,结果是一样的。还直接在根网格中测试了文本框的行为。这是 MainPage 中的 XAML:
<Page x:Class="App1.MainPage"
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:local="using:App1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Margin="0,40"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button Margin="20,0"
Content="Popup button"
Tapped="Button_Tapped" />
<Button Margin="20,0" Content="Flyout button">
<Button.Flyout>
<Flyout>
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button Grid.Column="1" Content="Test" />
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
<Popup x:Name="MyPopup"
Width="320"
Height="60"
IsLightDismissEnabled="True">
<Grid Width="320"
Height="60"
Background="WhiteSmoke"
Padding="12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button Grid.Column="1" Content="Test" />
</Grid>
</Popup>
<TextBox Grid.Row="1"
MinWidth="64"
MaxWidth="300"
Margin="0,40"
VerticalAlignment="Center" />
</Grid>
</Page>
以及打开弹出窗口的事件:
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
MyPopup.IsOpen = true;
}
问题是 Grid
不是 "focusable",因为它不是从 Control
派生的。一种方法是将 Grid
放在 ContentControl
或 ContentPresenter
.
中
另一种方法有点麻烦,但您可以在点击 Popup
内的 Grid
时以编程方式将焦点设置在按钮上:
<Popup
x:Name="MyPopup"
Width="320"
Height="60"
IsLightDismissEnabled="True">
<Grid
x:Name="Grid"
Width="320"
Height="60"
Background="WhiteSmoke"
Tapped="Grid_OnTapped"
Padding="12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button
Grid.Column="1"
Content="Test" />
</Grid>
</Popup>
还有 Tapped
处理程序,您通常在其中搜索任何不是 TextBox
的可聚焦控件。如果你没有,你可以放置一个不可见的 ContentControl
和 Opacity=0.01
例如,这将成为焦点元素:
private void Grid_OnTapped(object sender, TappedRoutedEventArgs e)
{
var grid = sender as Grid;
if(grid == null) return;
var controlToFocus = FindChild<Button>(grid);
controlToFocus.Focus(FocusState.Programmatic);
}
private static T FindChild<T>(DependencyObject parent) where T : DependencyObject
{
var childCount = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < childCount; i++)
{
var elt = VisualTreeHelper.GetChild(parent, i);
if (elt is T) return (T)elt;
var result = FindChild<T>(elt);
if (result != null) return result;
}
return null;
}
我有一个带有文本框和按钮控件的弹出窗口。 当我 click/tap 在 Popup 中的任何地方时,Textbox 不会失去焦点。 使文本框失去焦点的唯一方法是将焦点设置在按钮上。 我希望能够在不关闭弹出窗口或单击按钮的情况下从文本框中移除焦点。 此问题仅发生在 Popup 中。 我曾经将控件放在 Flyout 中,当用户在文本框外和 Flyout 内的任何地方单击时,文本框就会失去焦点。此外,当 Flyout 打开时,Textbox 会自动将焦点放在 Flyout 打开上。
我测试了文本框如何在新的空白 UWP 项目中失去焦点的不同行为,结果是一样的。还直接在根网格中测试了文本框的行为。这是 MainPage 中的 XAML:
<Page x:Class="App1.MainPage"
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:local="using:App1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Margin="0,40"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button Margin="20,0"
Content="Popup button"
Tapped="Button_Tapped" />
<Button Margin="20,0" Content="Flyout button">
<Button.Flyout>
<Flyout>
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button Grid.Column="1" Content="Test" />
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
<Popup x:Name="MyPopup"
Width="320"
Height="60"
IsLightDismissEnabled="True">
<Grid Width="320"
Height="60"
Background="WhiteSmoke"
Padding="12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button Grid.Column="1" Content="Test" />
</Grid>
</Popup>
<TextBox Grid.Row="1"
MinWidth="64"
MaxWidth="300"
Margin="0,40"
VerticalAlignment="Center" />
</Grid>
</Page>
以及打开弹出窗口的事件:
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
MyPopup.IsOpen = true;
}
问题是 Grid
不是 "focusable",因为它不是从 Control
派生的。一种方法是将 Grid
放在 ContentControl
或 ContentPresenter
.
另一种方法有点麻烦,但您可以在点击 Popup
内的 Grid
时以编程方式将焦点设置在按钮上:
<Popup
x:Name="MyPopup"
Width="320"
Height="60"
IsLightDismissEnabled="True">
<Grid
x:Name="Grid"
Width="320"
Height="60"
Background="WhiteSmoke"
Tapped="Grid_OnTapped"
Padding="12,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox VerticalAlignment="Center" />
<Button
Grid.Column="1"
Content="Test" />
</Grid>
</Popup>
还有 Tapped
处理程序,您通常在其中搜索任何不是 TextBox
的可聚焦控件。如果你没有,你可以放置一个不可见的 ContentControl
和 Opacity=0.01
例如,这将成为焦点元素:
private void Grid_OnTapped(object sender, TappedRoutedEventArgs e)
{
var grid = sender as Grid;
if(grid == null) return;
var controlToFocus = FindChild<Button>(grid);
controlToFocus.Focus(FocusState.Programmatic);
}
private static T FindChild<T>(DependencyObject parent) where T : DependencyObject
{
var childCount = VisualTreeHelper.GetChildrenCount(parent);
for (var i = 0; i < childCount; i++)
{
var elt = VisualTreeHelper.GetChild(parent, i);
if (elt is T) return (T)elt;
var result = FindChild<T>(elt);
if (result != null) return result;
}
return null;
}