mollwitz
mollwitz

Reputation: 213

C# universal app: automatically scroll to bottom of textbox after setting new text programmatically

{
   var stringBuilder = new StringBuilder(OutputTextBox.Text);
   stringBuilder.Append("sample text\n");
   OutputTextBox.Text = stringBuilder.ToString();
}

How to automatically scroll to the bottom of the textbox after inserting a new text? I have read that it had worked with the .append method. Unfortunately this method does not exist within universal apps. The textbox is read-only.

The .xaml looks like this:

<ScrollViewer Name="ScrollViewer" HorizontalAlignment="Left" Height="175" VerticalAlignment="Top" Width="337" RenderTransformOrigin="1.774,9.9" Margin="95,95,-370,-223">
            <TextBox x:Name="OutputTextBox" HorizontalAlignment="Left" Height="175" VerticalAlignment="Top" Width="337" RenderTransformOrigin="1.774,9.9" TextWrapping="Wrap" AcceptsReturn="True" IsReadOnly="True"/>
</ScrollViewer>

What I have tried to do is:

        await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            var stringBuilder = new StringBuilder(OutputTextBox.Text);
            stringBuilder.Append("sample text\n");
            OutputTextBox.Text = stringBuilder.ToString();
            ScrollViewer.ChangeView(0.0f, double.MaxValue, 1.0f);
        });

Upvotes: 1

Views: 1518

Answers (2)

Jay Zuo
Jay Zuo

Reputation: 15758

TextBox has an embedded ScrollViewer by default. We can find it in TextBox styles and templates. There is no need to put TextBox inside another ScrollViewer again.

Scrolling using a scroll-wheel or touch is automatically enabled when needed. However, vertical scrollbars are not shown by default. You can show the vertical scrollbars by setting the ScrollViewer.VerticalScrollBarVisibility to Auto on the embedded ScrollViewer, as shown here.

<TextBox AcceptsReturn="True" TextWrapping="Wrap" 
         MaxHeight="172" Width="300" Header="Description"
         ScrollViewer.VerticalScrollBarVisibility="Auto"/>

For more info, please see the Enable multi-line input section in the Remarks of TextBox class.

So to scroll to the bottom of a TextBox, we can get the embedded ScrollViewer first and then use ChangeView to scroll the text inside the TextBox. Following is a simple example:

private void ScrolltoBottom(TextBox textBox)
{
    var grid = (Grid)VisualTreeHelper.GetChild(textBox, 0);
    for (var i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++)
    {
        object obj = VisualTreeHelper.GetChild(grid, i);
        if (!(obj is ScrollViewer)) continue;
        ((ScrollViewer)obj).ChangeView(0.0f, ((ScrollViewer)obj).ExtentHeight, 1.0f);
        break;
    }
}

However, here is an issue when using ChangeView method, we can not scroll back with scroll-wheel or touch after we use this method in TextBox. As a workaround, we can use ScrollViewer.ScrollToVerticalOffset method provisionally.

private void ScrolltoBottom(TextBox textBox)
{
    var grid = (Grid)VisualTreeHelper.GetChild(textBox, 0);
    for (var i = 0; i < VisualTreeHelper.GetChildrenCount(grid); i++)
    {
        object obj = VisualTreeHelper.GetChild(grid, i);
        if (!(obj is ScrollViewer)) continue;
        //((ScrollViewer)obj).ChangeView(0.0f, ((ScrollViewer)obj).ExtentHeight, 1.0f);
        ((ScrollViewer)obj).ScrollToVerticalOffset(((ScrollViewer)obj).ExtentHeight);
        break;
    }
}

Upvotes: 4

Nejc Galof
Nejc Galof

Reputation: 2614

Try change view on ScrollViewer like this after setting new text:

ScrollViewer.ChangeView(0.0f, double.MaxValue, 1.0f);

or use ScrollViewer.ScrollToEnd();

And add to ScrollView this settings:

VerticalScrollBarVisibility="Visible" AllowDrop="False" ManipulationMode="Control"

You have like this:

<ScrollViewer Name="ScrollViewer" HorizontalAlignment="Left" Height="175" VerticalAlignment="Top" Width="337" RenderTransformOrigin="1.774,9.9" Margin="95,95,-370,-223" VerticalScrollBarVisibility="Visible" AllowDrop="False" ManipulationMode="Control">

Upvotes: 0

Related Questions