¿Cómo puedo desplazarme automáticamente hasta la parte inferior de un cuadro de texto multilínea?


Tengo un cuadro de texto con el .Propiedad multilínea establecida en true. A intervalos regulares, estoy añadiendo nuevas líneas de texto. Me gustaría que el cuadro de texto se desplace automáticamente a la entrada más baja (la más reciente) cada vez que se agrega una nueva línea. ¿Cómo logro esto?

Author: GWLlosa, 2009-05-22

11 answers

, A intervalos regulares, estoy añadiendo nuevas líneas de texto. Me gustaría que el cuadro de texto se desplace automáticamente a la entrada más baja (la más reciente) cada vez que se agrega una nueva línea.

Si usa TextBox.AppendText(string text), se desplazará automáticamente hasta el final del texto recién agregado. Evita el parpadeo de la barra de desplazamiento si lo estás llamando en un bucle.

También sucede que es un orden de magnitud más rápido que concatenar en la propiedad .Text. Aunque eso podría depender de la frecuencia con la que lo estés llamando; estaba probando con un bucle apretado.


Esto no se desplazará si se llama antes de que se muestre el cuadro de texto, o si el cuadro de texto no es visible (por ejemplo, en una pestaña diferente de un TabPanel). Véase el cuadro de texto .AppendText () no autoscrolling . Esto puede o puede no ser importante, dependiendo de si se requiere desplazamiento automático cuando el usuario no puede ver el cuadro de texto.

Parece que el método alternativo de las otras respuestas tampoco funciona en este caso. Una forma de evitarlo es realizar un desplazamiento adicional en el evento VisibleChanged:

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

Internamente, AppendText hace algo como esto:

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

Pero no debería haber ninguna razón para hacerlo manualmente.

(Si lo descompila usted mismo, verá que utiliza algunos métodos internos posiblemente más eficientes, y tiene lo que parece ser un caso especial menor.)

 347
Author: Bob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:01

Puede usar el siguiente fragmento de código:

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

Que se desplazará automáticamente hasta el final.

 137
Author: GWLlosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-22 14:58:50

Parece Que la interfaz ha cambiado en .NET 4.0. Existe el siguiente método que logra todo lo anterior. Como sugirió Tommy Engebretsen, ponerlo en un controlador de eventos TextChanged lo hace automático.

textBox1.ScrollToEnd();
 35
Author: JohnDRoach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-06 12:51:09

Intenta añadir el código sugerido al evento TextChanged:

private void textBox1_TextChanged(object sender, EventArgs e)
{
  textBox1.SelectionStart = textBox1.Text.Length;
  textBox1.ScrollToCaret();
}
 14
Author: GWLlosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-22 14:35:31

Necesitaba añadir una actualización:

textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
textBox1.Refresh();
 8
Author: h4nd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 01:35:39
textBox1.Focus()
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();

No funcionó para mí (Windows 8.1, cualquiera que sea la razón).
Y como todavía estoy en. NET 2.0, no puedo usar ScrollToEnd.

Pero esto funciona:

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;

    /// <summary>
    /// Scrolls the vertical scroll bar of a multi-line text box to the bottom.
    /// </summary>
    /// <param name="tb">The text box to scroll</param>
    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
    <System.Runtime.InteropServices.DllImport("user32.dll", CharSet := System.Runtime.InteropServices.CharSet.Auto)> _
    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

    ''' <summary>
    ''' Scrolls the vertical scroll bar of a multi-line text box to the bottom.
    ''' </summary>
    ''' <param name="tb">The text box to scroll</param>
    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
 7
Author: Stefan Steiger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-15 09:13:13

Encontré una diferencia simple que no se ha abordado en este hilo.

Si estás haciendo todas las llamadas ScrollToCarat() como parte del evento Load() de tu formulario, no funciona. Acabo de agregar mi llamada ScrollToCarat() al evento Activated() de mi formulario, y funciona bien.

Editar

Es importante hacer este desplazamiento solo la primera vez que se activa el evento Activated del formulario (no en activaciones posteriores), o se desplazará cada cuando se active su formulario, que es algo que probablemente no quieras.

Así que si solo estás atrapando el evento Activated() para desplazar el texto cuando se carga el programa, entonces puedes cancelar la suscripción al evento dentro del controlador de eventos, así: {[15]]}

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

Si tiene otras cosas que necesita hacer cada vez que se activa su formulario, puede establecer un bool a true la primera vez que se dispara su evento Activated(), por lo que no se desplaza en las activaciones posteriores, pero aún puede hacer las otras cosas que necesita hacer.

También, si su TextBox está en una pestaña que no es la SelectedTab, ScrollToCarat() no tendrá efecto. Así que necesitas al menos que sea la pestaña seleccionada mientras te desplazas. Puedes envolver el código en un par YourTab.SuspendLayout(); y YourTab.ResumeLayout(false); si tu formulario parpadea al hacer esto.

Fin de la edición

Espero que esto ayude!

 2
Author: Pete,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-24 01:36:23

Esto se desplazará hasta el final del cuadro de texto cuando se cambie el texto, pero aún así permite al usuario desplazarse hacia arriba

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

Probado en Visual Studio Enterprise 2017

 1
Author: Eric Shreve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-16 16:29:23

Para cualquier otra persona que aterrice aquí esperando ver una implementación de formularios web, debe usar el controlador de eventos EndRequest del Administrador de Solicitudes de página ( https://stackoverflow.com/a/1388170/1830512 ). Esto es lo que hice para mi cuadro de texto en una Página de Contenido de una Página Maestra, ignore el hecho de que no utilicé una variable para el control:

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);
 1
Author: Greg Greenleaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-14 19:35:02

Esto solo funcionó para mí...

TxtSerialLogging - >Text="";

TxtSerialLogging - >AppendText(s);

Probé todos los casos anteriores, pero el problema es que en mi caso el texto s puede disminuir, aumentar y también puede permanecer estático durante mucho tiempo. estático significa, longitud estática (líneas) pero el contenido es diferente.

Entonces, me enfrentaba a una situación de salto de línea al final cuando la longitud(líneas) permanece igual por algunas veces...

 0
Author: TooGeeky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-10 09:51:05

Utilizo una función para esto :

private void Log (string s) {
    TB1.AppendText(Environment.NewLine + s);
    TB1.ScrollToCaret();
}
 0
Author: DMike92,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-18 18:08:28