One of the best uses of our Routed Event extension is implementing missing system events in Silverlight, such as MouseWheel and RightButtonUp/Down. The API we provide is the same as WPF, so when Silverlight eventually gets support for those events, most probably you will not have to change much. Other good thing is that you do not need to write any JavaScript, or to know what's going on beneath. The bad thing is that you will have to enable the windowless mode of the Silverlight plug-in, which will slightly decrease the performance of your application.

To attach a Routed Event handler for the MouseWheel event on a ScrollViewer you need to add the following code in the constructor of your Silverlight Page:

Mouse.AddMouseWheelHandler(ScrollViewer1, new EventHandler<MouseWheelEventArgs>(OnMouseWheelHandler));  
 

 

Additionaly, you will have to declare the OnMouseWheelHandler method:

private static void OnMouseWheelHandler(object sender, MouseWheelEventArgs args)  
{  
    if (e.Handled)  
    {  
        return;  
    }  
    ScrollViewer scrollViewer = sender as ScrollViewer;  
    int scrollDelta = 40 * args.Delta / 3;  
    if (scrollViewer.ComputedVerticalScrollBarVisibility == Visibility.Visible)  
    {  
        scrollViewer.ScrollToVerticalOffset(  
            Math.Min(scrollViewer.ScrollableHeight,  
                 scrollViewer.VerticalOffset - scrollDelta));  
        e.Handled = true;  
    }  
    else if (scrollViewer.ComputedHorizontalScrollBarVisibility == Visibility.Visible)  
    {  
        scrollViewer.ScrollToHorizontalOffset(  
            Math.Min(scrollViewer.ScrollableWidth,  
                 scrollViewer.HorizontalOffset - scrollDelta));  
        e.Handled = true;  
    }  
}  
 

 

Unfortunately, the method above is not suitable for enhancing controls which have internal ScrollViewer, such as the standard ListBox, because you cannot get a reference to its ScrollViewer, in order to attach the Routed Event handler. In this case you could create a Class Handler for the ScrollViewer type:

EventManager.RegisterClassHandler(typeof(ScrollViewer), Mouse.MouseWheelEvent, new EventHandler<MouseWheelEventArgs>(OnMouseWheelHandler));  
 

 

In this case, since it will affect ALL ScrollViewer controls on the page, the OnMouseWheelHandler method should be slightly different in order to avoid interference with the Telerik controls, which already have mouse wheel support:

private static void OnMouseWheelHandler(object sender, MouseWheelEventArgs args)  
{  
    if (e.Handled || !ListBox1.IsAncestorOf(scrollViewer))   
    {  
        return;   
    }   
    ...  
}  
 

 

The check could be modified to exclude certain controls, e.g. if you have only a couple of Telerik controls on your page and lots ot other controls, containing ScrollViwers, you could disable the handler only for the Telerik controls and enhance all other ScrollViwers on the page.

The IsAncestorOf method is an extension method, that you could declare in some static class in your application as:

public static bool IsAncestorOf(this FrameworkElement target, FrameworkElement element)  
{  
    if (target == element)  
    {   
        return true;  
    }  
    FrameworkElement parent = VisualTreeHelper.GetParent(element) as FrameworkElement;  
    while (parent != null)  
    {  
        if (parent == target)  
        {  
            return true;  
        }  
        parent = VisualTreeHelper.GetParent(parent) as FrameworkElement;  
    }  
    return false;  
}  
 

 

Of course, the MouseWheel event is not limited to just scrolling ScrollViewer controls. For example, RadSlider and RadNumericUpDown use the MouseWheel event to change their values, you could zoom-in/out a DeepZoom image, etc. The possibilities are endless.

Attached is the source, containing the refactored code from the above. Happly MouseWheeling :)


About the Author

Valeri Hristov

Team Lead,
Platform Team

Related Posts

Comments

Comments are disabled in preview mode.