很难弄清楚控件为什么会失去焦点
本文关键字:失去 焦点 为什么 弄清楚 控件 很难 | 更新日期: 2023-09-27 17:58:48
我创建了一个自定义网格控件,每个单元格中都有可编辑的文本块。编辑由双击触发,如下所示:
void TextBlock_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (e.ClickCount == 2) Edit();
}
public void Edit()
{
TextBox.Text = TextBlock.Text;
TextBlock.Visibility = System.Windows.Visibility.Collapsed;
TextBox.Visibility = System.Windows.Visibility.Visible;
Dispatcher.BeginInvoke((ThreadStart)delegate
{
TextBox.Focus();
TextBox.SelectAll();
});
}
这部分工作符合预期。
我想让用户能够通过按下tab键前进或移动tab键返回来切换到下一个单元格。我添加了一个像这样触发的事件:
void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Tab)
{
e.Handled = true;
OnTab(System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.LeftShift) || System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.RightShift));
}
}
外部网格处理此事件,并在下一个或上一个可编辑单元格上调用Edit()
方法。只要我没有在文本框中键入,这几乎可以像预期的那样工作。出于某种原因,如果我键入了任何内容,LostFocus事件不仅会为当前单元格(在文本框上Edit()
调用Focus()
之后会触发),还会为下一个单元格触发。这是LostFocus事件的代码。(尽管我很确定这与此无关。)
void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
bool TextChanged = TextBox.Text != TextBlock.Text;
TextBlock.Text = TextBox.Text;
TextBlock.Visibility = System.Windows.Visibility.Visible;
TextBox.Visibility = System.Windows.Visibility.Collapsed;
if (TextChanged) OnTextChanged();
}
我可以创建某种奇特的门,让文本框忽略这个事件,但我更好奇的是,它为什么会启动,或者至少我该如何找到答案。
谢谢。
编辑:
所以很明显,即使有一些门控,我仍然被冲洗。我添加了一个名为Editing
的布尔值,并修改了Edit()
方法,使其工作方式如下:
public void Edit()
{
TextBox.Text = TextBlock.Text;
TextBlock.Visibility = System.Windows.Visibility.Collapsed;
TextBox.Visibility = System.Windows.Visibility.Visible;
Thread Task = new Thread(() =>
{
Editing = true;
Dispatcher.BeginInvoke((ThreadStart)delegate
{
System.Windows.Input.Keyboard.Focus(TextBox);
TextBox.SelectAll();
EditGate.Set();
});
EditGate.WaitOne();
Editing = false;
});
Task.Start();
}
然后更改了LostFocus处理程序:
void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (Editing) return;
// ... Some more code.
}
不幸的是,这也不起作用。事情最终是这样的:
- 当前单元格:编辑开始为false
- 当前单元格:选项卡事件激发
- 下一个单元格:调用了Edit()
- 下一个单元格:编辑设置为True
- 下一个单元格:调用了EditGate.WetOne()
- 下一个单元格:Keyboard.Focus()调用
- 当前单元格:焦点丢失(编辑仍然是错误的)
- 下一个单元格:调用了Textbox.SelectAll()
- 下一个单元格:调用了EditGate.Set()
- 下一个单元格:编辑设置为False
- 下一个单元格:焦点丢失(编辑现在为假)
我不知道为什么LostFocus事件在其他所有事件之后触发。它几乎知道我要做什么。:P
我认为这可能是由于KeyboardFocus
,在WPF中你可以设置"逻辑"焦点,KeyboardFocus
只是猜测,但当你在TextBox中键入时,会获得KeyBoardFocus
,这可能会改变逻辑焦点的状态。
这对我来说有点难测试,但试着在Edit()
方法中设置键盘焦点,看看会发生什么。
public void Edit()
{
TextBox.Text = TextBlock.Text;
TextBlock.Visibility = System.Windows.Visibility.Collapsed;
TextBox.Visibility = System.Windows.Visibility.Visible;
Dispatcher.BeginInvoke((ThreadStart)delegate
{
Keyboard.Focus(TextBox);
TextBox.SelectAll();
});
}
我一直在从代码后面操作WPF焦点时遇到问题,我想这是因为它的设计不是这样的,最好使用Xaml触发器对焦点进行排序(如果可能的话)
也许FocusManager类可能会有所帮助,在这里您可以添加或删除当前/下一个项目的焦点处理程序
FocusManager.RemoveLostFocusHandler(TextBox, TextBox_LostFocus);
FocusManager.AddLostFocusHandler(TextBox, TextBox_LostFocus);