c# – 使用ScrollViewer.ScrollToEnd()进行AutoScroll只能在调试时使用,事件处理程序太简单了
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 使用ScrollViewer.ScrollToEnd()进行AutoScroll只能在调试时使用,事件处理程序太简单了,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3453字,纯文字阅读大概需要5分钟。
内容图文
![c# – 使用ScrollViewer.ScrollToEnd()进行AutoScroll只能在调试时使用,事件处理程序太简单了](/upload/InfoBanner/zyjiaocheng/794/3b1e43ca92ec464c880cd557b43c3539.jpg)
查看this solution以获得更好的自动滚动功能我认为自己非常聪明地找到一个更简单的解决方案,但它只适用于调试会话:
private void scrollviewer_Messages_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
ScrollViewer sv = sender as ScrollViewer;
if (sv.VerticalOffset == sv.ScrollableHeight)
{
sv.ScrollToEnd();//debug breakpoint
}
return;
}
在向此ScrollViewer中的文本块添加内容时,自动滚动工作,文本的底部保持在视图中.当用户向上滚动,并添加更多内容时,底部不在视图中,自动滚动关闭,这很好.当用户滚动回到底部时,ScrollToEnd()应该重新打开自动滚动,但是当添加更多内容时,底部仍然会滚出视图.
当我设置断点时,我可以验证是否确实调用了ScrollToEnd().然后,在删除断点并添加更多内容后,autoscroll将再次运行.
我通过按下按钮,在ViewModel中使用代码和Binding来添加内容.所以我确信没有并发问题.添加内容和手动滚动之间有很长时间.
这真让我感到困惑,而我对我的简单自动滚动解决方案非常满意.这怎么可能不起作用?
编辑:
我发现自动滚动在滚动到底部之后再次起作用,但不知何故真的打到底部并不容易.我需要向下移动滑块,然后单击滚动条的向下箭头.我现在将尝试替换代码中的==符号以允许几个像素差异.
编辑:
这个问题是由内容是带有多行文本字符串和TextWrap的TextBlock引起的吗?
<ScrollViewer Name="scrollviewer_Messages" DockPanel.Dock="Top"
Height="100" Width="200"
ScrollChanged="scrollviewer_Messages_ScrollChanged">
<TextBlock Name="tb_Message"
Margin="10" TextWrapping="Wrap"
Text="{Binding Path=Messages}">
</TextBlock>
</ScrollViewer>
编辑:
将事件处理程序中的公式更改为:
sv.ScrollableHeight - sv.VerticalOffset < 20
我已经用< 10但是pushpraj(见下面的答案)让我尝试更大的数字.目前还不清楚为什么会这样,因为问题不在于没有调用ScrollToEnd(). 关于解决方案: 不需要< 20,因为它是关于分数的.一般来说,两个实数永远不会相等,但这不是真的.当滑块位于末尾时,偏移和高度的双数确实相等. 问题是,显然,ScrollToEnd / Bottom()在使用滑块滚动时不起作用.而已.我会把它称为一个错误,但它也可能是一个“功能”:当用户滑动它并期望控制时,不应该改变滑块的行为. 解决方法是首先我们将滑块滑动到最后,使Offset == Height.第二步是添加内容会增加高度,由于上面的错误,滑块会向上移动一点,在我的情况下大约15点.这会引发ScrollChanged事件,并且< 20的阈值足以获得ScrollToBottom的第二次调用.每次添加内容时都会执行此步骤2. 我之前的编辑提到单击向下按钮的工作方式类似.显然,ScrollToEnd适用于向下按钮. 当然,问题在于bug是一个bug.一次添加更多内容时,阈值可能不起作用,并且自动滚动可能会停止. 最终的解决方案,不是我希望的那么简单,但仍然不是太复杂,应该是我在下面的答案中的解决方案.
解决方法:
问题的原因是ScrollToEnd()与autoscroll无关.这个调用只是滚动到最后,就是这样.通过将调用放在事件处理程序中,它将经常滚动到结尾但是对于真正的自动滚动,有必要确定是谁触发了事件:用户通过移动滑块,或者滑动因为内容大小的更改而移动.通过查看ExtentHeight而不是忽略“无用”事件,此属性现在用于确定触发事件的人员或内容.
此解决方案将自动滚动位的状态保存在控件的标记中.将子类化为新的usercontrol AutoScrollViewer会更好.
毕竟,这个解决方案并不比上面提到的问题中的前一个解决方案“简单”,它只是一个变体,但它(希望)更准确.
/// <summary>
/// If the scrollviewer is at the bottom, keep the bottom in view.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void scrollviewer_Messages_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
ScrollViewer sv = sender as ScrollViewer;
bool AutoScrollToEnd = true;
if (sv.Tag != null)
{
AutoScrollToEnd = (bool)sv.Tag;
}
if (e.ExtentHeightChange == 0)// user scroll
{
AutoScrollToEnd = sv.ScrollableHeight == sv.VerticalOffset;
}
else// content change
{
if (AutoScrollToEnd)
{
sv.ScrollToEnd();
}
}
sv.Tag = AutoScrollToEnd;
return;
}
内容总结
以上是互联网集市为您收集整理的c# – 使用ScrollViewer.ScrollToEnd()进行AutoScroll只能在调试时使用,事件处理程序太简单了全部内容,希望文章能够帮你解决c# – 使用ScrollViewer.ScrollToEnd()进行AutoScroll只能在调试时使用,事件处理程序太简单了所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。