gpt4 book ai didi

wpf - 使用 IsFocusScope 选项时如何阻止 FocusManager 将焦点移到打开的弹出窗口之外

转载 作者:行者123 更新时间:2023-12-01 09:26:37 25 4
gpt4 key购买 nike

我有两个控件,一个 ToolBar 和一个 TextBox。 ToolBar 有一个 Button,它会打开一个 Popup,其中包含另一个 Button

当前行为:如果我在 TextBox 内单击,它会变成焦点,然后单击 ToolBar 中的按钮,这会打开一个弹出窗口 TextBox 仍然保持焦点并接收所有键盘输入。

现在我知道这是 ToolBar 所在的 FocusScope 内的项目的默认行为,但是当弹出窗口打开时我不需要这种行为。我该如何避免呢?

示例如下:

<Window x:Class="WpfApplication67.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
</Window.Resources>
<StackPanel HorizontalAlignment="Left" Width="400">
<ToolBar>
<ToggleButton Name="openButton">Open Popup</ToggleButton>
<Popup Focusable="True"
Placement="Right"
StaysOpen="False"
IsOpen="{Binding IsChecked, ElementName=openButton, Mode=TwoWay}"
PlacementTarget="{Binding ElementName=openButton}">
<StackPanel
Width="100"
Height="100"
Background="DarkGray"
Focusable="True">
<Button>More</Button>
</StackPanel>
</Popup>
</ToolBar>

<TextBox Text="Set focus on this..." />

</StackPanel>

编辑:我正在努力寻找关于谁将焦点移动到嵌套 FocusScope 内的按钮单击以及如何阻止某些按钮(如弹出窗口内的按钮)这样做的解释。

最佳答案

你主要有三个要求(有错请指正):

  1. 如果弹出窗口打开,焦点应该在 popUp 内部,即 StackPanel 上。
  2. 在弹出窗口关闭时,焦点应保留回文本框。
  3. 当点击 popUp 内的按钮时,焦点不应离开 popUp。

让我们一一挑选这些要求。

If pop up is opened, focus should be inside popUp i.e. on StackPanel.

就像我在评论中提到的那样,在 PopUp 的 Opened 事件上关注 stackPanel:

private void Popup_Opened(object sender, EventArgs e)
{
stackPanel.Focus();
}

On close of popUp, focus should retained back to textBox.

Hook Closed 事件并将焦点放回 TextBox:

private void Popup_Closed(object sender, EventArgs e)
{
textBox.Focus();
}

When button inside popUp is clicked, focus should not leave the popUp.

现在,棘手的部分来了。正如评论中提到的,一旦您单击弹出窗口内的按钮,焦点就会移到弹出窗口之外。

您可以阻止的是将处理程序附加到 stackPanel 的 PreviewLostKeyboardFocus 事件。在处理程序检查条件是否键盘焦点在弹出窗口中,设置 e.Handled = true 以便仅在此处处理事件并且不会引发将强制键盘的气泡事件焦点在 stackPanel 之外。

也就是说,如果您在 stackPanel besies 按钮中有另一个 TextBox,则处理事件也不允许您在 popUp 中移动焦点。为了避免这种情况,您可以检查新的焦点元素是否不属于 stackPanel,然后只处理该事件。

这是实现该目标的代码(在 StackPanel 的 PreviewLostKeyboardFocus 事件上添加处理程序):

private void stackPanel_PreviewLostKeyboardFocus(object sender, 
KeyboardFocusChangedEventArgs e)
{
var newFocusedChild = e.NewFocus as FrameworkElement;
bool isMovingWithinPanel = newFocusedChild != null
&& newFocusedChild.Parent == stackPanel;

// If keyboard focus is within stackPanel and new focused element is
// outside of stackPanel boundaries then only handle the event.
if (stackPanel.IsKeyboardFocusWithin && !isMovingWithinPanel)
e.Handled = true;
}

关于wpf - 使用 IsFocusScope 选项时如何阻止 FocusManager 将焦点移到打开的弹出窗口之外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22304926/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com