Adding mouse wheel support to ScrollViewer
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
Hi,lee
Do you have some samples about ComboBox and DataGrid(mouse wheel support)?
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
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;