DoubleClick Trigger for DataGrid in Silverlight and C#
Due to lack of double click event in Silverlight a custom implementation is needed.
The purpose of adding Trigger/Behavior has two main advantages.
First for the missing Triggers of Silverlilght controls and secondly these allow developers to interact with controls without writing any code in any future projects especially in case of MVVM pattern.
Double Click Trigger Class
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;
using System.Windows.Threading;namespace Projects.Infrastructure.Triggers
{
public class DataGridMouseDoubleClickTrigger : TriggerBase
{
private readonly DispatcherTimer timer;
private MouseButtonEventHandler _datagridMouseLeftButtonDownHandler;
private DateTime _lastMouseDownDateTime = DateTime.Now;
private bool _hasFirstMouseDownOccured = false;
private Point _firstMouseDownPosition;
protected override void OnAttached()
{
if (AssociatedObject != null)
{
_datagridMouseLeftButtonDownHandler = new MouseButtonEventHandler(OnGridViewMouseLeftButtonDown);
AssociatedObject.AddHandler(UIElement.MouseLeftButtonDownEvent, _gridViewMouseLeftButtonDownHandler, true);
}
}
protected override void OnDetaching()
{
if (AssociatedObject != null && _datagridMouseLeftButtonDownHandler != null)
{
AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonDownEvent, _datagridMouseLeftButtonDownHandler);
}
}
private void OnTimerTick(object sender, EventArgs e)
{
timer.Stop();
}
private static bool IsGridViewRow(DataGrid GridView, Point mousePosition, ref object rowDataContext)
{
GeneralTransform gt = GridView.TransformToVisual(Application.Current.RootVisual);
Point mousePositionOffset = gt.Transform(mousePosition);
IEnumerable hitElements = VisualTreeHelper.FindElementsInHostCoordinates(mousePositionOffset, GridView);
var gridViewRow = hitElements.OfType().FirstOrDefault();
if (gridViewRow != null)
{
rowDataContext = gridViewRow.DataContext;
}
return gridViewRow != null;
}
private void OnGridViewMouseLeftButtonDown(object sender, MouseButtonEventArgs args)
{
DateTime currentMouseDownDateTime = DateTime.Now;
TimeSpan timeSpanBetweenButtonDowns = currentMouseDownDateTime – _lastMouseDownDateTime;
if (timeSpanBetweenButtonDowns.TotalMilliseconds > 300 || _hasFirstMouseDownOccured == false)
{
_firstMouseDownPosition = args.GetPosition(AssociatedObject);
_hasFirstMouseDownOccured = true;
_lastMouseDownDateTime = DateTime.Now;
}
else
{
Point currentMousePosition = args.GetPosition(AssociatedObject);
object rowDataContext = null;
if ((Math.Abs(_firstMouseDownPosition.X – currentMousePosition.X) < 4 && Math.Abs(_firstMouseDownPosition.Y – currentMousePosition.Y) < 4)
&& IsGridViewRow(AssociatedObject, currentMousePosition, ref rowDataContext)
)
{
InvokeActions(rowDataContext);
}
_hasFirstMouseDownOccured = false;
}
}
}
}
XAML Code
DataGrid with one Column and binding of a command action on Double Click Trigger
xmlns:i=”clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity”
<sdk:DataGrid HorizontalAlignment=”Stretch” Margin=”5″ MaxWidth=”475″ Grid.Column=”6″ Grid.Row=”3″
ItemsSource=”{Binding GridDataSource}”
VerticalAlignment=”Stretch” CanUserResizeColumns=”False”
MinHeight=”120″ AutoGenerateColumns=”False”
SelectedItem=”{Binding SelectedRecord, Mode=TwoWay}”>
<sdk:DataGrid.Columns >
<sdk:DataGridTextColumn Binding=”{Binding ItemName, Mode=TwoWay}” Header=”Item Name” Width=”*” IsReadOnly=”True” />
</sdk:DataGrid.Columns>
<i:Interaction.Triggers>
<Triggers:DataGridMouseDoubleClickTrigger>
<Triggers:ExecuteCommandAction Command=”{Binding OpenItemCommand}” />
</Triggers:DataGridMouseDoubleClickTrigger>
</i:Interaction.Triggers>
</sdk:DataGrid>
View Model Class with Trigger bind command
{
public ICommand OpenItemCommand { get; set; }
public DataGridViewModel()
{
OpenItemCommand = new DelegateCommandprivate void ExecuteOpenItemCommand(object obj)
{
MessageBox.Show(“Double Click Trigger is fired to open current item.”);
}
}