views:

533

answers:

4

Datagrid in silverlight 3 toolkit is not responding to scrollwheel(mousewheel). Is there any way to get support of scroll wheel?

+3  A: 

Below is the behavior I am using. And below that is how you attach it to the datagrid in xaml.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Automation.Peers;
using System.Windows.Interactivity;
using System.Windows.Automation.Provider;
using System.Windows.Automation;
using System.Windows.Data;

namespace GLS.Gui.Helper.Behaviors
{
    public class MouseWheelScrollBehavior : Behavior<Control>
    {
        /// <summary>
        /// Gets or sets the peer.
        /// </summary>
        /// <value>The peer.</value>
        private AutomationPeer Peer { get; set; }

        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        /// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
        protected override void OnAttached()
        {
            this.Peer = FrameworkElementAutomationPeer.FromElement(this.AssociatedObject);

            if (this.Peer == null)
                this.Peer = FrameworkElementAutomationPeer.CreatePeerForElement(this.AssociatedObject);

            this.AssociatedObject.MouseWheel += new MouseWheelEventHandler(AssociatedObject_MouseWheel);
            base.OnAttached();
        }

        /// <summary>
        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
        /// </summary>
        /// <remarks>Override this to unhook functionality from the AssociatedObject.</remarks>
        protected override void OnDetaching()
        {
            this.AssociatedObject.MouseWheel -= new MouseWheelEventHandler(AssociatedObject_MouseWheel);
            base.OnDetaching();
        }

        /// <summary>
        /// Handles the MouseWheel event of the AssociatedObject control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseWheelEventArgs"/> instance containing the event data.</param>
        void AssociatedObject_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            //Do not handle already handled events
            if (e.Handled)
                return;

            this.AssociatedObject.Focus();

            int direction = Math.Sign(e.Delta);

            ScrollAmount scrollAmount =
                (direction < 0) ? ScrollAmount.SmallIncrement : ScrollAmount.SmallDecrement;

            if (this.Peer != null)
            {
                IScrollProvider scrollProvider =
                    this.Peer.GetPattern(PatternInterface.Scroll) as IScrollProvider;

                bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;

                if (scrollProvider != null && scrollProvider.VerticallyScrollable && !shiftKey)
                {
                    scrollProvider.Scroll(ScrollAmount.NoAmount, scrollAmount);
                    e.Handled = true;
                }
                else if (scrollProvider != null && scrollProvider.VerticallyScrollable && shiftKey)
                {
                    scrollProvider.Scroll(scrollAmount, ScrollAmount.NoAmount);
                    e.Handled = true;
                }


            }
        }
    }


}

How to attach the behavior:

<data:DataGrid>
            <i:Interaction.Behaviors>
                <b:MouseWheelScrollBehavior />
            </i:Interaction.Behaviors>
        </data:DataGrid>
Henrik Söderlund
Kudos to Andrea Boschin who wrote it: http://silverlightplayground.boschin.it/post/2009/07/10/Silverlight-30-RTW-An-universal-MouseWheelScrolling-behavior.aspx
Henrik Söderlund
A: 

An other way to do this (very basic example):
xaml:

<Grid x:Name="LayoutRoot">
    <data:DataGrid x:Name="dg" Height="100">
        <ScrollViewer.VerticalScrollBarVisibility>true</ScrollViewer.VerticalScrollBarVisibility>
    </data:DataGrid>


CS:

public partial class MainPage : UserControl
{
    IList<Person> list = new List<Person>();
    public MainPage()
    {
        InitializeComponent();
        list.Add(new Person("Pieter1","Nijs"));
        list.Add(new Person("Pieter2", "Nijs"));
        list.Add(new Person("Pieter3", "Nijs"));
        list.Add(new Person("Pieter4", "Nijs"));
        list.Add(new Person("Pieter5", "Nijs"));
        list.Add(new Person("Pieter6", "Nijs"));
        list.Add(new Person("Pieter7", "Nijs"));
        list.Add(new Person("Pieter8", "Nijs"));
        dg.ItemsSource = list;
        dg.MouseWheel += new MouseWheelEventHandler(dg_MouseWheel);
    }

    void dg_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (e.Delta < 0)
        {
            dg.ScrollIntoView(list[dg.SelectedIndex + 2], null);
        }
        else
        {
            dg.ScrollIntoView(list[dg.SelectedIndex - 2], null);
        }
    }
}

So, what I do here is quite simple!
I add an EventHandler to the DataGrid MouseWheel - event. In that handler I retreive the e.Delta (this is the amount the wheel has changed since the last time) so I know if the user scrolled up (positive Delta) or down (negative Delta). And then I call the ScrollIntoView-method of the DataGrid, where I can specify to what row the Grid should scroll to.
As mentioned, this is a very basic example! This is just to show you how it could work! You should add extra logic to make sure you don't go out of bounce!

Pieter Nijs
+1  A: 

I have used the MouseWheel Behavior for Silverlight from Silverlight.FX as a way to add mousewheel support to my apps. See http://www.nikhilk.net/Silverlight-MouseWheel.aspx for details.

DaveB
A: 

I am using the Silverlight Toolkit ScrollViewerExtensions in combination with a custom template for the datagrid. But i have the problem that the DataGrid does not look the same way it did before i applied the template... Someone can help me out?

<Style x:Key="StyleTable" TargetType="wcd:DataGrid">
    <Setter Property="CellStyle" Value="{StaticResource StyleTableCell}"/>
    <Setter Property="ColumnHeaderStyle" Value="{StaticResource StyleTableColumnHeader}"/>
    <Setter Property="RowHeaderStyle" Value="{StaticResource StyleTableRowHeader}"/>
    <Setter Property="RowStyle" Value="{StaticResource StyleTableRow}"/>
    <Setter Property="SelectionMode" Value="Single"/>
    <Setter Property="IsReadOnly" Value="true"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="GridLinesVisibility" Value="Horizontal"/>
    <Setter Property="ColumnTextStyle" Value="{StaticResource StyleColumnText}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="wcd:DataGrid">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <dataPrimitives:DataGridColumnHeadersPresenter x:Name="ColumnHeadersPresenter" />
                    <ScrollViewer Grid.Row="1" toolkit:ScrollViewerExtensions.IsMouseWheelScrollingEnabled="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" >
                        <dataPrimitives:DataGridRowsPresenter x:Name="RowsPresenter" />
                    </ScrollViewer>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
ceder