как автоматически прокрутить до конца многострочного текстового поля?

<p>у меня есть текстовое поле со свойством .multiline, установленным в true. я регулярно добавляю новые строки текста. я хотел бы, чтобы текстовое поле автоматически прокручивалось до самой нижней записи (самой новой) при добавлении новой строки. как мне это сделать?</p>

<blockquote> <p>я регулярно добавляю новые строки текста. я хотел бы, чтобы текстовое поле автоматически прокручивалось до самой нижней записи (самой новой) при добавлении новой строки.</p> </blockquote><p>если вы используете <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.textboxbase.appendtext.aspx"><code>textbox.appendtext(string text)</code></a> , он автоматически прокрутится до конца вновь добавленного текста. он избегает мерцающей полосы прокрутки, если вы вызываете ее в цикле.</p><p>это также происходит на порядок быстрее, чем конкатенация на свойство <code>.text</code>. хотя это может зависеть от того, как часто вы звоните; я тестировал с жесткой петлей.</p><hr><p>он не будет прокручиваться, если он вызывается до отображения текстового поля или если текстовое поле иначе не отображается (например, на другой вкладке tabpanel). смотрите <a href="https://stackoverflow.com/questions/18260702/textbox-appendtext-not-autoscrolling">textbox.appendtext () не автопрокрутка</a> . это может или не может быть важным, в зависимости от того, требуется ли автоматическая прокрутка, когда пользователь не видит текстовое поле.</p><p>кажется, что альтернативный метод из других ответов также не работает в этом случае. одним из способов решения этой проблемы является дополнительная прокрутка события <code>visiblechanged</code>:</p><pre><code>textbox.visiblechanged += (sender, e) => { if (textbox.visible) { textbox.selectionstart = textbox.textlength; textbox.scrolltocaret(); } }; </code></pre><hr><p>внутри <code>appendtext</code> делает что-то вроде этого:</p><pre><code>textbox.select(textbox.textlength + 1, 0); textbox.selectedtext = texttoappend; </code></pre><p>но не должно быть никаких причин делать это вручную.</p><p><sup>(если вы декомпилируете его самостоятельно, вы увидите, что он использует некоторые, возможно, более эффективные внутренние методы и имеет то, что кажется незначительным частным случаем.)</sup></p>

<p>вы можете использовать следующий фрагмент кода:</p><pre><code>mytextbox.selectionstart = mytextbox.text.length; mytextbox.scrolltocaret(); </code></pre><p>который будет автоматически прокручиваться до конца.</p>

<p>кажется, интерфейс изменился в <a href="http://en.wikipedia.org/wiki/.net\_framework">.net</a> 4.0. существует следующее <a href="http://msdn.microsoft.com/query/dev10.query?appid=dev10idef1&l=en-us&k=k%28system.windows.controls.primitives.textboxbase.scrolltoend%29;k%28targetframeworkmoniker-%22.netframework,version=v4.0%22%29;k%28devlang-csharp%29&rd=true">метод</a> , которое достигает всего вышеперечисленного. как предложил томми энгебретсен, помещение его в обработчик событий textchanged делает его автоматическим.</p><pre><code>textbox1.scrolltoend(); </code></pre>

<p>попробуйте добавить предложенный код в событие textchanged:</p><pre><code>private void textbox1\_textchanged(object sender, eventargs e) { textbox1.selectionstart = textbox1.text.length; textbox1.scrolltocaret(); } </code></pre>

<p>мне нужно было добавить обновление:</p><pre><code>textbox1.selectionstart = textbox1.text.length; textbox1.scrolltocaret(); textbox1.refresh(); </code></pre>

<pre><code>textbox1.focus() textbox1.selectionstart = textbox1.text.length; textbox1.scrolltocaret(); </code></pre><p>не работает для меня (windows 8.1, независимо от причины).<br> и так как я все еще на .net 2.0, я не могу использовать scrolltoend.<br> <br> но это работает:</p><pre><code>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); } } </code></pre><p>vb.net:</p><pre><code>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 </code></pre>

<p>я нашел простую разницу, которая не была рассмотрена в этой теме.</p><p>если вы делаете все вызовы <code>scrolltocarat()</code> как часть события <code>load()</code> вашей формы, это не сработает. я просто добавил свой вызов <code>scrolltocarat()</code> в событие моей формы <code>activated()</code>, и он работает нормально.</p><p><strong>edit</strong></p><p>эту прокрутку важно выполнять только при первом запуске события формы <code>activated</code> (не при последующих активациях), или оно будет прокручиваться <strong>каждые</strong> при активации вашей формы, чего вы, вероятно, не хотите.</p><p>поэтому, если вы перехватываете только событие <code>activated()</code> для прокрутки текста при загрузке программы, вы можете просто отписаться от события внутри самого обработчика события, таким образом:</p><pre><code>activated -= new system.eventhandler(this.form1\_activated); </code></pre><p>если у вас есть другие вещи, которые вам нужно делать при каждой активации формы, вы можете установить для <code>bool</code> значение true при первом запуске вашего события <code>activated()</code>, поэтому вы не будете прокручивать последующие активации, но все равно сможете выполнять другие действия, которые вы выполняете. нужно сделать.</p><p>кроме того, если ваше <code>textbox</code> находится на вкладке, которая не является <code>selectedtab</code>, <code>scrolltocarat()</code> не будет иметь никакого эффекта. так что вам нужно, по крайней мере, сделать его выбранной вкладкой во время прокрутки. вы можете обернуть код в пары <code>yourtab.suspendlayout();</code> и <code>yourtab.resumelayout(false);</code>, если ваша форма мерцает при этом.</p><p><strong>конец редактирования</strong></p><p>надеюсь это поможет!</p>

<p>это будет прокручивать до конца текстового поля, когда текст изменяется, но все же позволяет пользователю прокручивать вверх</p><pre><code>outbox.selectionstart = outbox.text.length; outbox.scrolltoend(); </code></pre><p>протестировано на visual studio enterprise 2017</p>

<p>для тех, кто находится здесь, ожидающих увидеть реализацию веб-форм, вы хотите использовать обработчик событий endrequest менеджера запросов страниц ( <a href="https://stackoverflow.com/a/1388170/1830512">https://stackoverflow.com/a/1388170/1830512</a> ). вот что я сделал для своего textbox на странице содержимого с мастер-страницы. пожалуйста, не обращайте внимания на тот факт, что я не использовал переменную для элемента управления:</p><pre><code>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); </code></pre>

<p>это работало только для меня ...</p><p>txtseriallogging-> text = "";</p><p>txtseriallogging-> appendtext (ы);</p><p>я перепробовал все вышеописанные случаи, но проблема в том, что в моем случае текст может уменьшаться, увеличиваться и также может оставаться статичным в течение длительного времени. статические средства, статическая длина (строки), но содержание другое.</p><p>итак, я столкнулся с ситуацией скачка одной строки в конце, когда длина (строки) остается неизменной в течение нескольких раз ...</p>

<p>я использую функцию для этого:</p><pre><code>private void log (string s) { tb1.appendtext(environment.newline + s); tb1.scrolltocaret(); } </code></pre>