Подтвердить что ты не робот

Лучший способ прокрутки до конца ScrollViewer

В настоящее время единственный способ, которым я получил свой код для автоматического прокрутки до конца, когда я добавляю новый элемент, следующий:

XAML:

<ScrollViewer x:Name="chatViewScroller" HorizontalAlignment="Left" Height="201" Margin="0,32,0,0" VerticalAlignment="Top" Width="475" Background="#7FFFFFFF">
    <StackPanel x:Name="chatViewContent" />
</ScrollViewer>

код:

                chatViewContent.Children.Add(
                    new TextBlock() {
                        Text = text,
                        FontSize = 18,
                        TextWrapping = Windows.UI.Xaml.TextWrapping.Wrap,
                        Margin = new Thickness(10, 3, 10, 0),
                        Foreground = new Windows.UI.Xaml.Media.SolidColorBrush(
                            isServerMessage ? Windows.UI.Colors.Purple : Windows.UI.Colors.Black)
                    });
                await Task.Delay(10);
                chatViewScroller.ScrollToVerticalOffset(chatViewScroller.ScrollableHeight);

Это приемлемый способ сделать это? Должен ли я ждать какой-то случайный период времени?

4b9b3361

Ответ 1

Использование ActualHeight не сработало для меня (мне еще предстоит выяснить, почему), но используя ScrollableHeight, как это сделал трюк:

// adding item to ItemsControl...
// ...
_scrollViewer.UpdateLayout();
_scrollViewer.ScrollToVerticalOffset(_scrollViewer.ScrollableHeight);

Ответ 2

Для Windows Phone 8.1 я использую это:

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

Ответ 3

никакая случайная асинхронность никогда не является ответом на что-либо на любом языке, кроме, может быть, JavaScript... у него всегда есть этот "запах кода", который вы знаете?

правильный способ сделать это - принудительно "обновить" меры ScrollViewer синхронно, чтобы включить вновь добавленных детей, вызвав ScrollViewer.Measure(Size)

после "повторной оценки" ScrollableHeight будет правильным значением, и вы можете использовать его, как обычно.

вот так:

    private void AddMessage(string text, Color color)
    {
        var message = new TextBlock
        {
            Text = text,
            FontSize = 18,
            TextWrapping = TextWrapping.Wrap,
            Margin = new Thickness(10, 3, 10, 0),
            Foreground = new SolidColorBrush(color),
        };

        chatViewContent.Children.Add(message);

        chatViewScroller.Measure(chatViewScroller.RenderSize);
        chatViewScroller.ScrollToVerticalOffset(chatViewScroller.ScrollableHeight);
    }

the Size, который мы используем здесь, это RenderSize, который может быть технически некорректным в некоторых случаях экстремальных краев, но он близок к идеально идеальному для наших целей. вы также можете технически использовать сколь угодно большой Size для Measure(Size) и получить тот же эффект. что лучше всего подходит для вашего решения, надеюсь, что это поможет -ck

Ответ 4

Для универсального приложения WindowsPhone вы можете использовать:

 var scrollableHeight = ScrollViewer.ScrollableHeight;
        if (scrollableHeight > 0)
        {
           ScrollViewer.ScrollToVerticalOffset(scrollableHeight);
        }

Ответ 5

На мой взгляд, лучший вариант - наследовать от ScrollViewer следующим образом:

public partial class AutoScrollViewer
{        
    public AutoScrollViewer()
    {
        InitializeComponent();
        this.SizeChanged += (sender, args) => this.ScrollToBottom();
    }
}

и XAML

<ScrollViewer x:Class="AutoScrollViewer"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ScrollViewer>

Затем вы можете использовать непосредственно в XAML новый класс без дополнительного кода, за которым полезно, особенно если у вас есть "чистый" код MVVM.

Ответ 7

Я использовал следующее:

ScrollViewer viewer = GetScrollViewer();
if (viewer != null)
{
    viewer.ScrollToVerticalOffset(viewer.ActualHeight);
}

Другое решение состоит в том, чтобы поместить элементы в ListBox и использовать метод ScrollIntoView

Ответ 8

ScrollViewer.ScrollToVerticalOffset(ScrollViewer.ActualHeight) должен работать, но если ваш код только что обновил содержимое средства просмотра прокрутки, вы можете вызвать ScrollViewer.UpdateLayout() перед прокруткой, чтобы ScrollViewer.ActualHeight заработал на сегодняшний день.