I would like to create the following behaviour in a ScrollViewer
that wraps ContentControl
:
When the ContentControl
height grows , the ScrollViewer
should automatically scroll to the end. This is easy to achive by using ScrollViewer.ScrollToEnd()
.
However, if the user uses the scroll bar, the automatic scrolling shouldn't happen anymore. This is similar to what happens in VS output window for example.
The problem is to know when a scrolling has happened because of user scrolling and when it happened because the content size changed. I tried to play with the ScrollChangedEventArgs
of ScrollChangedEvent
, but couldn't get it to work.
Ideally, I do not want to handle all possible Mouse and keyboard events.
You can use ScrollChangedEventArgs.ExtentHeightChange to know if a ScrollChanged is due to a change in the content or to a user action... When the content is unchanged, the ScrollBar position sets or unsets the auto-scroll mode. When the content has changed you can apply auto-scrolling.
Code behind:
private Boolean AutoScroll = true;
private void ScrollViewer_ScrollChanged(Object sender, ScrollChangedEventArgs e)
{
// User scroll event : set or unset auto-scroll mode
if (e.ExtentHeightChange == 0)
{ // Content unchanged : user scroll event
if (ScrollViewer.VerticalOffset == ScrollViewer.ScrollableHeight)
{ // Scroll bar is in bottom
// Set auto-scroll mode
AutoScroll = true;
}
else
{ // Scroll bar isn't in bottom
// Unset auto-scroll mode
AutoScroll = false;
}
}
// Content scroll event : auto-scroll eventually
if (AutoScroll && e.ExtentHeightChange != 0)
{ // Content changed and auto-scroll mode set
// Autoscroll
ScrollViewer.ScrollToVerticalOffset(ScrollViewer.ExtentHeight);
}
}