Как автоматически перейти к нижней части многострочного текстового поля?

У меня есть текстовое поле с свойством .Multiline, равным true. Через определенные промежутки времени я добавляю к нему новые строки текста. Я хотел бы, чтобы текстовое поле автоматически прокручивалось до самой нижней записи (самой новой) всякий раз, когда добавляется новая строка. Как это сделать?

Через определенные промежутки времени я добавляю к нему новые строки текста. Я хотел бы, чтобы текстовое поле автоматически прокручивалось до самой нижней записи (самой новой) всякий раз, когда добавляется новая строка.

Если вы используете TextBox.AppendText(string text) , он автоматически прокручивается до конца добавленного текста. Это позволяет избежать мерцающей полосы прокрутки, если вы вызываете ее в цикле.

Это также оказывается на порядок быстрее, чем конкатенация на свойство .Text . Хотя это может зависеть от того, как часто вы это называете; Я тестировал плотную петлю.


Это не будет прокручиваться, если оно вызывается до отображения текстового поля или если текстовое поле в противном случае не видно (например, на другой вкладке TabPanel). См. TextBox.AppendText (), а не автопрокрутку . Это может быть или не быть важно, в зависимости от того, требуется ли автосканирование, когда пользователь не может видеть текстовое поле.

Похоже, что альтернативный метод из других ответов также не работает в этом случае. Один из способов – выполнить дополнительную прокрутку в событии VisibleChanged :

 textBox.VisibleChanged += (sender, e) => { if (textBox.Visible) { textBox.SelectionStart = textBox.TextLength; textBox.ScrollToCaret(); } }; 

Внутри AppendText делает что-то вроде этого:

 textBox.Select(textBox.TextLength + 1, 0); textBox.SelectedText = textToAppend; 

Но не должно быть никаких оснований делать это вручную.

(Если вы декомпилируете его самостоятельно, вы увидите, что он использует некоторые, возможно, более эффективные внутренние методы и имеет то, что кажется небольшим частным случаем.)

Вы можете использовать следующий fragment кода:

 myTextBox.SelectionStart = myTextBox.Text.Length; myTextBox.ScrollToCaret(); 

который автоматически прокрутится до конца.

Кажется, интерфейс изменился в .NET 4.0. Существует следующий метод, который достигает всего вышеперечисленного. Как предложил Томми Энгебретсен, помещение его в обработчик событий TextChanged делает его автоматическим.

 textBox1.ScrollToEnd(); 

Попробуйте добавить предлагаемый код к событию TextChanged:

 private void textBox1_TextChanged(object sender, EventArgs e) { textBox1.SelectionStart = textBox1.Text.Length; textBox1.ScrollToCaret(); } 

Мне нужно было добавить обновление:

 textBox1.SelectionStart = textBox1.Text.Length; textBox1.ScrollToCaret(); textBox1.Refresh(); 
 textBox1.Focus() textBox1.SelectionStart = textBox1.Text.Length; textBox1.ScrollToCaret(); 

не работает для меня (Windows 8.1, независимо от причины).
И поскольку я все еще на .NET 2.0, я не могу использовать ScrollToEnd.

Но это работает:

 public class Utils { [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)] private static extern int SendMessage(System.IntPtr hWnd, int wMsg, System.IntPtr wParam, System.IntPtr lParam); private const int WM_VSCROLL = 0x115; private const int SB_BOTTOM = 7; ///  /// Scrolls the vertical scroll bar of a multi-line text box to the bottom. ///  /// The text box to scroll public static void ScrollToBottom(System.Windows.Forms.TextBox tb) { if(System.Environment.OSVersion.Platform != System.PlatformID.Unix) SendMessage(tb.Handle, WM_VSCROLL, new System.IntPtr(SB_BOTTOM), System.IntPtr.Zero); } } 

VB.NET:

 Public Class Utils  _ Private Shared Function SendMessage(hWnd As System.IntPtr, wMsg As Integer, wParam As System.IntPtr, lParam As System.IntPtr) As Integer End Function Private Const WM_VSCROLL As Integer = &H115 Private Const SB_BOTTOM As Integer = 7 '''  ''' Scrolls the vertical scroll bar of a multi-line text box to the bottom. '''  ''' The text box to scroll Public Shared Sub ScrollToBottom(tb As System.Windows.Forms.TextBox) If System.Environment.OSVersion.Platform <> System.PlatformID.Unix Then SendMessage(tb.Handle, WM_VSCROLL, New System.IntPtr(SB_BOTTOM), System.IntPtr.Zero) End If End Sub End Class 

Я нашел простое отличие, которое не было рассмотрено в этом streamе.

Если вы выполняете все ScrollToCarat() как часть события Load() , это не сработает. Я просто добавил свой ScrollToCarat() в событие Activated() моей формы, и он отлично работает.

редактировать

Важно пропустить только прокрутку Activated события в первый раз (не при последующих активациях), или он будет прокручиваться каждый раз, когда ваша форма активирована, чего вы, вероятно, не хотите.

Поэтому, если вы только улавливаете событие Activated() чтобы прокручивать текст, когда загружается ваша программа, вы можете просто отказаться от подписки на событие внутри самого обработчика событий, таким образом:

 Activated -= new System.EventHandler(this.Form1_Activated); 

Если у вас есть другие вещи, которые вам нужно делать каждый раз, когда ваша форма активирована, вы можете установить bool в true при первом Activated() события Activated() , чтобы вы не прокручивали последующие активации, но все равно можете сделать другое вещи, которые вам нужно сделать.

Кроме того, если ваш TextBox находится на вкладке, которая не является SelectedTab , ScrollToCarat() будет иметь никакого эффекта. Поэтому вам нужно хотя бы сделать выбранную вкладку во время прокрутки. Вы можете обернуть код в свой YourTab.SuspendLayout(); и YourTab.ResumeLayout(false); если ваша форма мерцает, когда вы это делаете.

Конец редактирования

Надеюсь это поможет!

Это будет прокручиваться до конца текстового поля при изменении текста, но все же позволяет пользователю прокручивать вверх

 outbox.SelectionStart = outbox.Text.Length; outbox.ScrollToEnd(); 

тестируется на Visual Studio Enterprise 2017

Для тех, кто приземляется здесь, ожидая увидеть реализацию webforms, вы хотите использовать обработчик событий endRequest менеджера запросов страниц ( https://stackoverflow.com/a/1388170/1830512 ). Вот что я сделал для своего TextBox на странице содержания с главной страницы, пожалуйста, проигнорируйте тот факт, что я не использовал переменную для элемента управления:

 var prm = Sys.WebForms.PageRequestManager.getInstance(); function EndRequestHandler() { if ($get('<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>') != null) { $get('<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>').scrollTop = $get('<%= ((TextBox)StatusWindow.FindControl("StatusTxtBox")).ClientID %>').scrollHeight; } } prm.add_endRequest(EndRequestHandler); 

Это работало только для меня …

txtSerialLogging-> Text = “”;

txtSerialLogging-> AppendText (ы);

Я пробовал все вышеперечисленные случаи, но проблема в том, что текст s может уменьшаться, увеличиваться и также может оставаться статичным в течение длительного времени. статические значения, статическая длина (строки), но контент отличается.

Итак, я столкнулся с одной ситуацией с прыжками в конце, когда длина (линии) остается той же в течение некоторого времени …

Для этого я использую функцию:

 private void Log (string s) { TB1.AppendText(Environment.NewLine + s); TB1.ScrollToCaret(); } 
Давайте будем гением компьютера.