如何取消输入焦点更改?(How do I cancel input focus change?)

在WPF应用程序中,我想实现身份验证逻辑:仅当用户登录时,他才能够编辑某个文本框ia对话框。

我想要的是以下行为:

如果用户已登录,则可以单击文本框并像往常一样开始编辑其内容。

如果用户没有登录,他仍然可以单击文本框,但是应该在登录对话框中提示他。 完成登录对话后,他应该回到文本框中,现在处于编辑模式。

如果用户取消登录对话框(未登录),则输入焦点应移至包含文本框的对话框的“取消”按钮,从而阻止他编辑文本框的内容。

我试过这样挂钩PreviewGotKeyboardFocus事件:

private void TextBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { bool loggedIn = ExecuteLogin(); //shows the login dialog and returns new login status if (!loggedIn) { CancelButton.Focus(); e.Handled = true; } }

只要用户完成登录过程,它确实可以正常工作,但如果他取消登录对话框,则不会将输入焦点转移到取消按钮。 此外,事件处理程序被多次调用(对话框中的每个文本框一次),并且整个系统似乎搞砸了(应用程序的进程在应用程序关闭时不会终止 - 之后必须将其终止)。

我应该改变什么以获得我想要的行为?

In a WPF application I want to implemement authentication logic: Only if a user is logged in he should be able to edit a certain textbox i a dialog box.

What I want is the following behavior:

If the user is logged in, he can click the text box and start editing its contents just as usual.

If the user is not logged in, he should still be able to click the text box, but he should then be prompted whith the login-dialog. After having completed the login-dialog, he should find himself back in the textbox, now in edit mode.

If the user cancels the login-dialog (without logging in), the input focus should move to the Cancel button of the dialog that contains the text box, thus preventing him from editing the textbox's contents.

I have tried hooking into the PreviewGotKeyboardFocus event this way:

private void TextBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { bool loggedIn = ExecuteLogin(); //shows the login dialog and returns new login status if (!loggedIn) { CancelButton.Focus(); e.Handled = true; } }

It does indeed work fine as long as the user completes the login procedure, but if he cancels the login dialog instead, it does not transfer the input focus to the cancel button. Further the event handler is called multiple times (once for each text box in my dialog), and the whole system seems to be messed up (the application's process does not terminate when the application is closed - it must be killed afterwards).

What should I change to obtain the behavior I want?

最满意答案

以下示例代码对我来说是预期的。 单击中间的TextBox,在对话框中回答“否”,然后按[enter]。

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private bool _handleEvent = true; private void TextBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { if (!_handleEvent) return; bool loggedIn = ExecuteLogin(); //shows the login dialog and returns new login status if (!loggedIn) { CancelButton.Focus(); e.Handled = true; } } public bool ExecuteLogin() => MessageBox.Show("Login?", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes; private void CancelButton_Click(object sender, RoutedEventArgs e) { MessageBox.Show("click"); } }
<StackPanel> <TextBox /> <TextBox PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" /> <TextBox /> <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" /> </StackPanel>

请注意,如果您使用键盘导航到按钮,则有意仅显示虚线对焦边框:

WPF按钮在启动或激活窗口期间具有键盘焦点(虚线边框)

当您提出问题时,您还应始终记住创建一个Minimal,Complete和Verifiable示例: https : //stackoverflow.com/help/mcve

The following sample code works as expected for me. Click on the TextBox in the middle, answer "No" in the dialog and press [enter].

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private bool _handleEvent = true; private void TextBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { if (!_handleEvent) return; bool loggedIn = ExecuteLogin(); //shows the login dialog and returns new login status if (!loggedIn) { CancelButton.Focus(); e.Handled = true; } } public bool ExecuteLogin() => MessageBox.Show("Login?", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes; private void CancelButton_Click(object sender, RoutedEventArgs e) { MessageBox.Show("click"); } }
<StackPanel> <TextBox /> <TextBox PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" /> <TextBox /> <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" /> </StackPanel>

Note that the dotted focus border is intentionally only shown if you are navigating to the Button by using the keyboard:

WPF Button to have Keyboard focus (dotted border around) during the startup or activation of window

You should also always remember to create a Minimal, Complete, and Verifiable example when you ask a question: https://stackoverflow.com/help/mcve

更多推荐