I created a quick example that places in image in a ScrollViewer, starts a DispatcherTimer and then prints out the ScrollViewer.HorizontalOffset every 200 ms. From the example I noticed some strange behavior – if I grab the image and scroll around by small amounts, say 60 pixels or so, the HorizontalOffset value never changes. Is there a reason that the ScrollViewer is not reporting its position correctly?
EDIT: I also tried grabbing the ScrollBar (named “HorizontalScrollBar”) in the ScrollViewer and checking its Value property but I get the same results.
EDIT2: It appears this bug only happens on Mango build 7712 (even if the app is built for 7.0). I’ll close this out and hope that its fixed in the final build.
Sample code. On my machine I can drag the image for large extents without getting an update. I seem to only get an update ever 120 or so increments of value. I would like to get the update at least every 10-20 pixels.
<Grid x:Name="LayoutRoot" Background="Transparent">
<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" x:Name="Scroll">
<Image Source="Jellyfish.jpg" Stretch="None"/>
</ScrollViewer>
</Grid>
MainPage.xaml.cs:
// Constructor
public MainPage()
{
InitializeComponent();
this.Loaded += (s, e) =>
{
var scrollBar = Scroll.FindVisualChild("HorizontalScrollBar") as ScrollBar;
scrollBar.ValueChanged += (s1, e1) => Debug.WriteLine(DateTime.Now + " " + scrollBar.Value);
};
}
ExtensionMethods.cs:
public static class ExtensionMethods
{
public static FrameworkElement FindVisualChild(this FrameworkElement root, string name)
{
FrameworkElement temp = root.FindName(name) as FrameworkElement;
if (temp != null)
return temp;
foreach (FrameworkElement element in root.GetVisualDescendents())
{
temp = element.FindName(name) as FrameworkElement;
if (temp != null)
return temp;
}
return null;
}
public static IEnumerable<FrameworkElement> GetVisualDescendents(this FrameworkElement root)
{
Queue<IEnumerable<FrameworkElement>> toDo = new Queue<IEnumerable<FrameworkElement>>();
toDo.Enqueue(root.GetVisualChildren());
while (toDo.Count > 0)
{
IEnumerable<FrameworkElement> children = toDo.Dequeue();
foreach (FrameworkElement child in children)
{
yield return child;
toDo.Enqueue(child.GetVisualChildren());
}
}
}
public static IEnumerable<FrameworkElement> GetVisualChildren(this FrameworkElement root)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
yield return VisualTreeHelper.GetChild(root, i) as FrameworkElement;
}
}
The infrequent scroll event updating is part of the performance improvements in Mango:
http://blogs.msdn.com/b/slmperf/archive/2011/06/02/listbox-scrollviewer-performance-improvement-for-mango-and-how-it-impacts-your-existing-application.aspx
The fix is to change the ScrollViewer’s ManipulationMode as follows: