Stick vertical scrollbar to bottom only when dragged to bottom

518 views Asked by At

tI've got a Textbox inside a Scrollviewer:

<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
    <TextBox IsReadOnly="True" TextWrapping="Wrap" Text="{Binding Messages, Converter={StaticResource TimedStringListToStringConverter}, UpdateSourceTrigger=PropertyChanged}"/>
</ScrollViewer>

I want to set the vertical scrollbar to bottom only when i manually drag it to the bottom, otherwise it mustn't move from its position.

Ideas?

2

There are 2 answers

2
almulo On BEST ANSWER

To achieve what you want (scrolling to the end only when you've already manually scrolled down there) and using the TextBox's own ScrollViewer, you just have to handle the TextChanged event and in code-behind do this:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    var textBox = sender as TextBox;
    var max = (textBox.ExtentHeight - textBox.ViewportHeight);
    var offset = textBox.VerticalOffset;

    if (max != 0 && max == offset)
        this.Dispatcher.BeginInvoke(new Action(() =>
            {
                textBox.ScrollToEnd();
            }),
            System.Windows.Threading.DispatcherPriority.Loaded);
}

If you need to use the extra ScrollViewer around the TextBox, then just use that ScrollViewer's ExtentHeight, ViewportHeight and VerticalOffset, and call that ScrollViewer's ScrollToBottom (instead of TextBox's ScrollToEnd).

Keep in mind that the text input caret position is not changing, so if you try to enter text manually, the scroll is gonna jump to wherever the caret is.

0
goobering On

If your TextBox is ReadOnly then I'd be inclined to use codebehind to call ScrollToHome. If you use the TextBox's own ScrollViewer you'll need to set an explicit Height to force the ScrollViewer to display.

XAML

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <TextBox x:Name="MyTextBox"
                Grid.Row="0"
                Width="80"
                Height="100"
                FontSize="20"
                IsReadOnly="True"
                ScrollViewer.HorizontalScrollBarVisibility="Auto"
                ScrollViewer.VerticalScrollBarVisibility="Auto"
                TextChanged="MyTextBox_TextChanged"
                TextWrapping="Wrap" />
    <Button Grid.Row="1"
            Width="50"
            Height="50"
            Click="Button_Click"
            Content="OK" />
</Grid>

Codebehind

private void MyTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    MyTextBox.ScrollToHome();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    MyTextBox.Text += "TEXT ";
}