| Comments

As you may know, most wheel support is detected at the browser level.  In Silverlight, this makes adding mouse wheel support an interop action with the HTML host.  While people have implemented it, it has mostly been for the use of DeepZoom applications.  In fact, the latest DeepZoom Composer tool actually adds this support now if you choose to have a Silverlight project as a part of the output of the collection.

But what about other controls, namely ScrollViewer?  Having content in ScrollViewer enables ScrollBar functionality but doesn’t automatically respond to mouse wheel actions.  Adam Cooper has solved this gap problem by adding a helper class to which you can attach to your ScrollViewer object.  Let’s say our XAML is this:

   1: <ScrollViewer x:Name="MyScroller" Width="300" Height="100" Background="AliceBlue">
   2:     <TextBlock TextWrapping="Wrap">
   3:         Even if you use my workaround ...
   4:     </TextBlock>
   5: </ScrollViewer>

If we run the application our content is scrollable, but not with the wheel.  Add Adam’s control reference and these lines of code in our Page.xaml.cs class:

   1: using Cooper.Silverlight.Controls;
   2:  
   3: public Page()
   4: {
   5:     InitializeComponent();
   6:  
   7:     ScrollViewerMouseWheelSupport.Initialize(this);
   8:  
   9:     MyScroller.AddMouseWheelSupport();
  10: }

and we have automatic wheel scroll support.  Great job Adam!  His post talks about various other methods of nesting and how it actually works.

It would be nice if you could just create MyCustomScrollViewer but unfortunately you cannot subclass ScrollViewer for some reason. 

Some might be also wondering how they could add this functionality to ListBox, since the default control template for ListBox contains a ScrollViewer.  Good question I thought as well and I went about trying.  There are some challenges to using the default ListBox.  First, the visual tree of the template is only loaded after the layout has been updated.  I’m not sure why it isn’t in Loaded, but in LayoutUpdated it is available.  So from this event you can use VisualTreeHelper.GetChild(ListBox, 0) to get the root node of the template.  From there you can use FindName(“ScrollViewer”) to get to the ScrollViewer in the default control template.

Here’s where it gets funky.

While you can add Adam’s extension method just fine with no exceptions, it doesn’t exactly work when rendered.  Here’s the code I used:

   1: void DefaultList_LayoutUpdated(object sender, EventArgs e)
   2: {
   3:     // root node
   4:     Grid rootGrid = VisualTreeHelper.GetChild(DefaultList, 0) as Grid;
   5:     
   6:     // find the ScrollViewer
   7:     ScrollViewer scroller = rootGrid.FindName("ScrollViewer") as ScrollViewer;
   8:     
   9:     // add the mouse wheel support
  10:     scroller.AddMouseWheelSupport();
  11:  
  12:     // stop looking
  13:     DefaultList.LayoutUpdated -= new EventHandler(DefaultList_LayoutUpdated);
  14: }

And while no errors occur, I believe other events in the ItemTemplate are eating my events.  If anyone has any wise thoughts, post the comments here.  But either way, thanks Adam for this great utility for ScrollViewer!

Please enjoy some of these other recent posts...

Comments