Нашел обходной путь для этого, не уверенный, будет ли он работать в чистой среде WPF, в моем случае я использую WPF в основном для Windows Forms, используя при необходимости WPF UserControls.
Вместо немедленного вызова BringIntoFocus () отложите его на более поздний момент, добавив в очередь, которая обрабатывается таймером. Например:
System.Windows.Forms.Timer DeferredActionTimer = new System.Windows.Forms.Timer() { Interval = 200 };
Queue<Action> DeferredActions = new Queue<Action>();
void DeferredActionTimer_Tick(object sender, EventArgs e) {
while(DeferredActions.Count > 0) {
Action act = DeferredActions.Dequeue();
act();
}
}
В конструкторе форм или в событии OnLoad добавьте:
DeferredActionTimer.Tick += new EventHandler(DeferredActionTimer_Tick);
DeferredActionTimer.Enabled = true;
Наконец, вместо прямого вызова TextPointer.Paragraph.BringIntoView();
, назовите это так:
DeferredActions.Enqueue(() => TextPointer.Paragraph.BringIntoView());
Обратите внимание, что таймер Windows Forms запускает события в главном потоке (через цикл обработки сообщений). Если вам нужно использовать другой таймер, вам нужно немного дополнительного кода. Я бы порекомендовал вам использовать System.Timers.Timer
, а не System.Threading.Timer
(он немного более ориентирован на многопоточность). Вы также должны были бы обернуть действие в Dispatcher.Invoke
структуру. В моем случае таймер WinForms работает как брелок.