Многострочное текстовое поле с автоматической вертикальной прокруткой
В Интернете есть много похожих вопросов по Интернету, включая SO, но предлагаемые решения в моем случае не работают.
Сценарий: есть текстовое поле журнала в xaml
<TextBox Name="Status"
Margin="5"
Grid.Column="1"
Grid.Row="5"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="600"
Height="310"/>
Есть методы в кодировании, которые выполняют некоторую работу и добавляют в это текстовое поле несколько многострочных (возможно, проблем?) сообщений:
private static void DoSomeThings(TextBox textBox)
{
// do work
textBox.AppendText("Work finished\r\n"); // better way than Text += according to msdn
// do more
textBox.AppendText("One more message\r\n");
...
}
private static void DoSomething2(TextBox textBox)
{
// same as first method
}
Вам нужно прокрутить до нижней части текстового поля после всех действий. Tried ScrollToEnd(), ScrollToLine, обертывание текстового поля в обходные пути ScrollViewer, Selection и Caret, добавление ScrollToEnd в TextChanged. Ничто из этого не работает, после того, как строки выполнения, которые превышают высоту текстового поля, все равно нужно прокручивать вручную. Извините за повторяющийся вопрос, я думаю, что у меня отсутствуют некоторые незначительные проблемы, которые могут быть быстро решены кем-то, у которого есть новое видение проблемы. Спасибо заранее.
Ответы
Ответ 1
В соответствии с этим вопросом: TextBox.ScrollToEnd не работает, если TextBox находится на неактивной вкладке
Вам нужно сфокусировать текстовое поле, обновить позицию каретки, а затем прокрутить до конца:
Status.Focus();
Status.CaretIndex = Status.Text.Length;
Status.ScrollToEnd();
ИЗМЕНИТЬ
Пример TextBox:
<TextBox TextWrapping="Wrap" VerticalScrollBarVisibility="Auto"
AcceptsReturn="True" Name="textBox"/>
Ответ 2
Если вы превратите его в простой пользовательский элемент управления, вам не нужен код для прокрутки.
public class ScrollingTextBox : TextBox {
protected override void OnInitialized (EventArgs e) {
base.OnInitialized(e);
VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
}
protected override void OnTextChanged (TextChangedEventArgs e) {
base.OnTextChanged(e);
CaretIndex = Text.Length;
ScrollToEnd();
}
}
Если вы используете WPF, было бы гораздо лучше использовать привязку, а не передавать текстовое поле в коде.
Ответ 3
Спасибо! Я добавил это, чтобы вспомнить исходный фокус:
var oldFocusedElement = FocusManager.GetFocusedElement(this);
this.textBox.Focus();
this.textBox.CaretIndex = this.textBox.Text.Length;
this.textBox.ScrollToEnd();
FocusManager.SetFocusedElement(this, oldFocusedElement);