可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Currently, the only way I have gotten my code to auto scroll to the end when I add a new item is the following:
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>
Code:
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);
Is this the accepted way of doing it? Do I have to wait for some random period of time?
回答1:
Using ActualHeight did not work for me (I have yet to figure out why) - but using ScrollableHeight like this did the the trick:
// adding item to ItemsControl...
// ...
_scrollViewer.UpdateLayout();
_scrollViewer.ScrollToVerticalOffset(_scrollViewer.ScrollableHeight);
回答2:
For Windows Phone 8.1 I use this:
MyScrollViewer.ChangeView(0.0f, double.MaxValue, 1.0f);
回答3:
In my opinion best option is to inherit from ScrollViewer in following way:
public partial class AutoScrollViewer
{
public AutoScrollViewer()
{
InitializeComponent();
this.SizeChanged += (sender, args) => this.ScrollToBottom();
}
}
and XAML
<ScrollViewer x:Class="AutoScrollViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ScrollViewer>
Then you can use directly in XAML the new class without additional code behind which is usefull especailly when you have "pure" MVVM code.
回答4:
no random asynchronicity is never the answer to anything in any language except maybe JavaScript... it just always has that "code smell" you know?
the proper way to do this is to force a "refresh" of the measure of the ScrollViewer
synchronously to include the newly added children by calling ScrollViewer.Measure(Size)
after you "re-measure" the ScrollableHeight
will be the proper value and you can use it as you normally would..
like this:
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
we are using here is the RenderSize
which could technically be incorrect in some extreme edge cases, but it is pretty close to perfectly ideal for our purposes. you could also technically use an arbitrarily large Size
for the Measure(Size)
and get the same effect. whatever works best for your solution, hope this helps -ck
回答5:
For WindowsPhone Universal app you can use:
var scrollableHeight = ScrollViewer.ScrollableHeight;
if (scrollableHeight > 0)
{
ScrollViewer.ScrollToVerticalOffset(scrollableHeight);
}
回答6:
If you are working with .NET 3.0 or later, you can use ScrollViewer.ScrollToBottom()
.
MSDN doc: http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.scrolltobottom(v=vs.110).aspx
回答7:
I've used the following:
ScrollViewer viewer = GetScrollViewer();
if (viewer != null)
{
viewer.ScrollToVerticalOffset(viewer.ActualHeight);
}
Another solution is to put the items into a ListBox
and use the ScrollIntoView method
回答8:
ScrollViewer.ScrollToVerticalOffset(ScrollViewer.ActualHeight) should work, but if your code has just now updated the content of the scroll viewer, you may want to call ScrollViewer.UpdateLayout() before scrolling, so that ScrollViewer.ActualHeight will be up to date.
回答9:
For Windows Phone 8.0, you can use
MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.ExtentHeight - MyScrollViewer.ViewportHeight);
Please also refer to http://msdn.microsoft.com/en-us/library/windows/apps/system.windows.controls.scrollviewer.verticaloffset(v=vs.105).aspx