Возникла странная проблема, когда мне нужно переключить фокус с RichTextBox. XAML для моего приложения выглядит следующим образом:
<Window Name = "MyWindow" x:Class = "WpfBasics.MainWindow"
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:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WpfBasics"
mc:Ignorable = "d"
Title = "MainWindow" Height = "600" Width = "400">
<StackPanel>
<TextBlock>Box 1:</TextBlock>
<RichTextBox x:Name = "Box1" TextChanged = "Box1_TextChanged" />
<TextBlock>Box 2:</TextBlock>
<RichTextBox x:Name = "Box2" />
</StackPanel>
</Window>
Со следующим кодом (только соответствующий бит):
private void Box1_TextChanged(object sender, TextChangedEventArgs e)
{
Box2.Focus();
}
В тот момент, когда я использую Box1, Focus выдает следующее исключение:
System.InvalidOperationException: «Невозможно повторно открыть объект отмены, пока другой объект уже открыт».
Заглянув в CallStack, я считаю, что проблема вызвана обработчиком событий LostFocus на RichTextBox.
Пример довольно надуманный для простоты. Мой вариант использования - форма, в которой фокус должен измениться после ввода действительного значения.
Ах я вижу. тогда может сработать упомянутый мной обходной путь. вызовите свой метод ChangeFocus в событии TextChanged, если введено допустимое значение.
Просто попробовал, и проблема остается. Когда я смотрю на стек вызовов, это вызовы Undo и _FlushPendingInputItems(TextEditor This), которые вызывают проблему. На данный момент я предполагаю, что RichTextBoxes используют какую-то общую очередь, доступ к которой осуществляется одновременно.





Основываясь на предоставленной вами информации, я создал образец проекта, который, похоже, работает. Попробуйте это:
private void Box1_TextChanged(object sender, TextChangedEventArgs e)
{
RichTextBox textBox = sender as RichTextBox;
var text = new TextRange(textBox.Document.ContentStart, textbox.Document.ContentEnd).Text;
if (IsValid(text))
{
Dispatcher.BeginInvoke((Action)ChangeFocus);
}
}
private void ChangeFocus()
{
Box2.Focus();
}
private bool IsValid(string text)
{
var plainText = text.Substring(0, text.Length - 2);
if (plainText == "hello world")
return true;
return false;
}
Спасибо! Это отлично работает в моем случае. Есть ли у вас какое-либо представление о том, почему отправка фокуса изменений, похоже, позволяет избежать этой проблемы? - Или почему это не проблема штатного TextBox?
Кажется странным, что вы хотите изменить фокус сразу после ввода текста в текстовое поле ...