Looking at this solution for better autoscanning, I considered myself so smart as to find an easier solution, but it only works in a debugging session:
private void scrollviewer_Messages_ScrollChanged(object sender, ScrollChangedEventArgs e) { ScrollViewer sv = sender as ScrollViewer; if (sv.VerticalOffset == sv.ScrollableHeight) { sv.ScrollToEnd();
When adding content to a text block, this ScrollViewer has autoscrolling, the bottom of the text remains in sight. When the user scrolls up and more content is added, the lower part leaves the field of view, autoscrolling is turned off, and this is normal. When the user scrolls back, ScrollToEnd () should turn on auto-scanning again, but when more content is added, the bottom still scrolls out of sight.
When I set a breakpoint, I can check if ScrollToEnd () is actually called. Then, by removing the breakpoint and adding more content, autoscrolling works again.
I add content by clicking a button, with code in ViewModel and Binding. Therefore, I am sure that there is no problem with concurrency. There is a lot of time between adding content and manually scrolling.
It really puzzled me, while I was so pleased with my simple auto-scroll solution. How can this not work?
edit:
I found out that autoscroll works again after scrolling back, but for some reason it’s not so easy to hit from below. I need to move the slider down, And press the down arrow on the scroll bar. Now I will experiment with replacing the == sign in my code to resolve a few pixel difference.
edit:
Could this be a problem because the content is a TextBlock with multi-line text string and TextWrap?
<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>
edit:
The problem disappeared with a formula change in the event handler:
sv.ScrollableHeight - sv.VerticalOffset < 20
I already experimented with < 10 , but pushpraj (see answer below) made me try big numbers. It is not yet clear why this works, since the problem is not that ScrollToEnd() not called.
About the decision:
<20 not required, because we are talking about fractional numbers. In general, two real numbers are never equal, but this is not true here. The double numbers for offset and height are really equal when the slider is at the end.
The problem is that ScrollToEnd/Bottom() does not seem to work when scrolling with the slider. It. I would call it a mistake, but it can also be a “feature”: you cannot change the behavior of the slider while the user is sliding and waiting for control.
The fix is that first we move the slider to the end, doing an offset == Height. The second step is that adding content will increase the height, due to the above error the slider will move a little, in my case about 15 points. This raises the ScrollChanged event, and the threshold value <20 is large enough to receive a second ScrollToBottom call. This step two occurs every time the content is added.
My previous edit regarding pressing the down button works the same way. ScrollToEnd seems to work for the down button.
The trick, of course, is that a mistake is a mistake. If more content is added at the same time, the threshold may not work, and auto-scanning may stop.
The final solution, not as simple as I expected, but still not too complicated, should be in my answer below.