Come faccio a scorrere automaticamente fino alla fine di una casella di testo multilinea?

Ho una casella di testo con la proprietà .Multiline impostata su true. A intervalli regolari, aggiungo nuove righe di testo. Vorrei che la casella di testo scorra automaticamente nella voce in basso (la più recente) ogni volta che viene aggiunta una nuova riga. Come posso realizzare questo?

A intervalli regolari, aggiungo nuove righe di testo. Vorrei che la casella di testo scorra automaticamente nella voce in basso (la più recente) ogni volta che viene aggiunta una nuova riga.

Se usi TextBox.AppendText(string text) , scorrerà automaticamente fino alla fine del testo appena aggiunto. Evita la barra di scorrimento tremolante se la stai chiamando in loop.

Accade anche che sia un ordine di grandezza più veloce della concatenazione sulla proprietà .Text . Anche se ciò potrebbe dipendere da quanto spesso lo chiami; Stavo testando con un loop stretto.


Questo non scorrerà se viene chiamato prima che la casella di testo sia mostrata, o se la casella di testo non sia altrimenti visibile (ad esempio in una scheda diversa di un TabPanel). Vedi TextBox.AppendText () non lo scorrimento automatico . Questo può o non può essere importante, a seconda se si richiede lo scorrimento automatico quando l’utente non può vedere la casella di testo.

Sembra che anche il metodo alternativo rispetto alle altre risposte non funzioni in questo caso. Un modo per VisibleChanged è eseguire lo scrolling VisibleChanged sull’evento VisibleChanged :

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

Internamente, AppendText fa qualcosa del genere:

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

Ma non ci dovrebbero essere motivi per farlo manualmente.

(Se lo decompilate da soli, vedrete che usa metodi interni forse più efficienti, e ha quello che sembra essere un caso speciale minore.)

Puoi utilizzare il seguente snippet di codice:

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

che scorrerà automaticamente fino alla fine.

Sembra che l’interfaccia sia cambiata in .NET 4.0. C’è il seguente metodo che raggiunge tutto quanto sopra. Come suggeriva Tommy Engebretsen, metterlo in un gestore di eventi TextChanged lo rende automatico.

 textBox1.ScrollToEnd(); 

Prova ad aggiungere il codice suggerito all’evento TextChanged:

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

Ho bisogno di aggiungere un aggiornamento:

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

non ha funzionato per me (Windows 8.1, qualunque sia la ragione).
E poiché sono ancora su .NET 2.0, non posso usare ScrollToEnd.

Ma questo funziona:

 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 

Ho trovato una semplice differenza che non è stata affrontata in questa discussione.

Se stai facendo tutte le chiamate ScrollToCarat() come parte dell’evento Load() del tuo modulo, non funziona. Ho appena aggiunto la mia chiamata ScrollToCarat() mio modulo e funziona correttamente.

modificare

È importante fare questo scorrimento solo quando viene Activated evento Activated della prima volta (non nelle triggerszioni successive), o scorrerà ogni volta che si triggers il modulo, che probabilmente non si desidera.

Quindi, se intendi solo l’evento Activated() per far scorrere il testo quando il programma viene caricato, puoi semplicemente annullare l’iscrizione all’evento all’interno del gestore di eventi stesso, quindi:

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

Se hai altre cose che devi fare ogni volta che il tuo modulo è triggersto, puoi impostare un bool su true la prima volta che viene Activated() evento Activated() , in modo da non scorrere sulle triggerszioni successive, ma puoi comunque fare l’altro cose che devi fare

Inoltre, se il tuo TextBox trova su una scheda che non è SelectedTab , ScrollToCarat() non avrà alcun effetto. Quindi è necessario almeno renderlo la scheda selezionata mentre si sta scorrendo. Puoi avvolgere il codice in un YourTab.SuspendLayout(); e YourTab.ResumeLayout(false); coppia se il tuo sfarfallio forma quando si esegue questa operazione.

Fine modifica

Spero che questo ti aiuti!

Questo scorrerà fino alla fine della casella di testo quando il testo viene modificato, ma consente comunque all’utente di scorrere verso l’alto

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

testato su Visual Studio Enterprise 2017

Per chiunque altro stia pianificando di vedere un’implementazione di webforms, si desidera utilizzare il gestore di eventi endRequest del Gestore richieste di pagine ( https://stackoverflow.com/a/1388170/1830512 ). Ecco cosa ho fatto per il mio TextBox in una pagina di contenuto da una pagina master, per favore ignora il fatto che non ho usato una variabile per il controllo:

 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); 

Questo ha funzionato solo per me …

txtSerialLogging-> Text = “”;

txtSerialLogging-> AppendText (s);

Ho provato tutti i casi sopra, ma il problema è nel mio caso il testo può diminuire, aumentare e può anche rimanere statico per un lungo periodo. mezzi statici, lunghezza statica (linee) ma il contenuto è diverso.

Quindi, stavo affrontando una situazione di salto di linea alla fine quando la lunghezza (linee) rimane la stessa per alcune volte …

Io uso una funzione per questo:

 private void Log (string s) { TB1.AppendText(Environment.NewLine + s); TB1.ScrollToCaret(); }