Home > Silverlight > Adding mouse wheel support to ScrollViewer

Adding mouse wheel support to ScrollViewer

September 24, 2008 lee Leave a comment Go to comments

As we know there is no MouseWheel support to scroll as of Beta 2 and there are many ways out there to do the same

here is another way to do the same

Lets start with a couple of ListBoxes one which we add MouseWheel support and other not

  <Canvas>
        <ListBox x:Name=”list1″
                 Width=”200″
                 Height=”200″
                 local:Page.AddMouseWheelSupport=”true”></ListBox>     
        <ListBox x:Name=”list3″
                 Margin=”250, 0,0,0″
                 Width=”200″
                 Height=”200″></ListBox>
    </Canvas>

you will see a datagrid(in the samplecode). I thought it uses ScrollViewer. looks like it doesn’t so this technique wont work with that. This should work with any control that has ScrollViewer, did not try for any other Control.

Created a Attached property like this

public static bool GetAddMouseWheelSupport(DependencyObject obj)
        {
            return (bool)obj.GetValue(AddMouseWheelSupportProperty);
        }

        public static void SetAddMouseWheelSupport(DependencyObject obj, bool value)
        {
            obj.SetValue(AddMouseWheelSupportProperty, value);
        }

        // Using a DependencyProperty as the backing store for AddMouseWheelSupport.  This enables animation, styling, binding, etc…
        public static readonly DependencyProperty AddMouseWheelSupportProperty =
            DependencyProperty.RegisterAttached(“AddMouseWheelSupport”, typeof(bool), typeof(Page), new PropertyMetadata(ValueChanged));

        static void ValueChanged(DependencyObject obj,DependencyPropertyChangedEventArgs args)
        {
          
        }

you can see that we added the attached property to the 1st listbox

local:Page.AddMouseWheelSupport=”true”

we did not add this attribute to the 2nd listbox, so one of them will have the support and other wont

The main logic is in the function OnMouseWheel.1st part of the code is copied from Mike snow’s Blog, along with code for hooking up the events

 HtmlPage.Window.AttachEvent(“DOMMouseScroll”, OnMouseWheel);
 HtmlPage.Window.AttachEvent(“onmousewheel”, OnMouseWheel);
 HtmlPage.Document.AttachEvent(“onmousewheel”, OnMouseWheel);

 private void OnMouseWheel(object sender, HtmlEventArgs args){   
            double mouseDelta = 0;   
            ScriptObject e = args.EventObject;     // Mozilla and Safari   
            if (e.GetProperty(“detail”) != null)     {       
                mouseDelta = ((double)e.GetProperty(“detail”));   
            }   
            // IE and Opera   
            else if (e.GetProperty(“wheelDelta”) != null)        
                mouseDelta = ((double)e.GetProperty(“wheelDelta”));    

            List<UIElement> elements = this.HitTest(new Point(args.ClientX, args.ClientY)) as List<UIElement>;
            Control control = null;
            for (int i = 0; i < elements.Count-1; i++)
            {

                if (elements[i].GetType() == typeof(ListBox))
                {
                    control = elements[i] as Control;
                    break;
                }
             
            }

            if (control == null)
                return;
           
            mouseDelta = Math.Sign(mouseDelta);
            if ((bool)control.GetValue(AddMouseWheelSupportProperty))
            {
                ScrollViewer sv = GetChild<ScrollViewer>(control);
                if (sv == null)
                    return;
                if (mouseDelta == 1)
                    sv.ScrollToVerticalOffset(sv.VerticalOffset – 30);
                else
                    sv.ScrollToVerticalOffset(sv.VerticalOffset + 30);
            }
        }

What we are doing is doing a HitTest with ClientX and ClientY positions  to get a list of elements and checking is there is a listbox in the list of elements returned.
If we find one and the AttachedProperty ‘AddMouseWheelSupportProperty’ is set we get the ScrollViewer from the VisualTree and change the verticaloffset by some amount (30 in the sample)

you can download the code here

Categories: Silverlight Tags: ,
  1. Ak
    November 21, 2008 at 6:53 am | #1

    Hi,lee

    Do you have some samples about ComboBox and DataGrid(mouse wheel support)?

  2. lee
    November 21, 2008 at 4:43 pm | #2

    AK,
    I uploaded a sample (http://cid-71b364b59919d1e8.skydrive.live.com/self.aspx/Public/blog%20files/DataGrid%20mouse%20scroll.zip)
    instead of finding scrollviewer we have to find a DataGridRowsPresenter

    there are couple of bugs
    1. it scrolls only till 2nd row when you scroll up
    2. after the user scrolls using mouse wheel and then uses scrollbar or viceversa. the code wont work without some additional changes

  3. Don McLennan
    December 1, 2008 at 9:47 pm | #3

    With Silverlight 2.0, HitTest is moved to VisualTreeHelper.FindTestElementsInHostCoordinates. Replace

    List elements = this.HitTest(new Point(args.ClientX, args.ClientY)) as List

    with

    List elements = VisualTreeHelper.FindElementsInHostCoordinates(new Point(args.ClientX, args.ClientY),this) as List;

  1. September 25, 2008 at 4:48 am | #1