这很奇怪,我什至不知道要搜索什么,但相信我,我知道了。
我有一个文本框并绑定(bind)到它的 OnTextChanged
事件是下面的方法。
此处的目的是为文本框提供焦点,将光标移动到 TextBox 的末尾并将焦点返回到实际焦点(通常是按钮)。问题是,在我将焦点发送回最初聚焦的元素之前,似乎 TextBox 没有“重绘”(因为缺少更好的词?),因此光标位置不会在屏幕上更新(尽管所有属性都认为它有) .
目前,我已经粗暴地破解了这一点,基本上将先前聚焦项目的重新聚焦延迟 10 毫秒,并在不同的线程中运行它,以便 UI 有时间更新。现在,这显然是任意时间,并且在我的机器上运行良好,但在旧机器上运行此应用程序的人可能会遇到问题。
有没有正确的方法来做到这一点?我想不通。
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
{
if (sender == null) return;
var box = sender as TextBox;
if (!box.IsFocused)
{
var oldFocus = FocusManager.GetFocusedElement(FocusManager.GetFocusScope(this));
box.Select(box.Text.Length, 0);
Keyboard.Focus(box); // or box.Focus(); both have the same results
var thread = new Thread(new ThreadStart(delegate
{
Thread.Sleep(10);
Dispatcher.Invoke(new Action(() => oldFocus.Focus()));
}));
thread.Start();
}
}
编辑
我的一个新想法是在 UI 完成更新后运行 oldFocus.Focus() 方法,所以我尝试了以下方法,但我得到了相同的结果:(
var oldFocus = FocusManager.GetFocusedElement(FocusManager.GetFocusScope(this));
Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
{
box.Select(box.Text.Length, 0);
box.Focus();
}));
Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => oldFocus.Focus()));
最佳答案
你在正确的轨道上,问题是你的 .Focus()
调用坚持,您需要在调度程序中将调用延迟到稍后时间。
而不是使用 DispatcherPriority
Send 的值(最高),请尝试使用 Dispatcher 将焦点设置在稍后的 DispatcherPriority,例如 Input。
Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(delegate() {
oldFocus.Focus(); // Set Logical Focus
Keyboard.Focus(oldFocus); // Set Keyboard Focus
}));
如您所见,我还设置了键盘焦点。
WPF 可以有多个焦点范围,一个以上的元素可以有逻辑焦点 (IsFocused = true
)。但是,只有一个元素可以拥有键盘焦点并接收键盘输入。
关于c# - WPF TextBox 移动光标和改变焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13995489/