Contrib: Blend Triger for GridPresenter Mouse Double Click

1 reply. Last post: January 20, 2011 9:19 PM by Glenn Layaar
Tags :
  • (None)
  • New Discussion
  • New Question
  • New Product Feedback

Just thought I'd share this snippet for others that may find this code useful. I had a read only grid that I wanted to execute a viewmodel command in response to a double click anywhere on a row, this is adapted from a trigger I wrote for another grid control. (To get this to work with a UXListBox create a new copy of this class and replace "GridPresenter" with "UXListBox" and "GirdPresenterRowElement" with "UXListBoxItem").


using System;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    using System.Linq;
    using System.Collections.Generic;
    using System.Windows.Media;
    using Intersoft.Client.Data.DataPresenter;
    public class IntersoftGridPresenterRowMouseDoubleClickTrigger : TriggerBase<GridPresenter>
    {
        private static readonly Type TriggerType = typeof(IntersoftGridPresenterRowMouseDoubleClickTrigger);
        private MouseButtonEventHandler _gridViewMouseLeftButtonUpHandler;
        private DateTime _lastMouseUpDateTime = DateTime.Now;
        private bool _hasFirstMouseUpOccured = false;
        private Point _firstMouseUpPosition;
        #region Dependency Properties
        #region DelayBetweenClicks Dependency Property
        public static readonly DependencyProperty DelayBetweenClicksProperty =
           DependencyProperty.Register("DelayBetweenClicks", typeof(TimeSpan), TriggerType,
           new PropertyMetadata(TimeSpan.FromMilliseconds(500), OnDelayBetweenClicksPropertyChanged));
        private static void OnDelayBetweenClicksPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((IntersoftGridPresenterRowMouseDoubleClickTrigger)sender).OnDelayBetweenClicksPropertyChanged(e);
        }
        protected virtual void OnDelayBetweenClicksPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
        }
        public TimeSpan DelayBetweenClicks
        {
            get { return (TimeSpan)GetValue(DelayBetweenClicksProperty); }
            set { SetValue(DelayBetweenClicksProperty, value); }
        }
        #endregion DelayBetweenClicks Dependency Property
        #region AllowedPixelMargin Dependency Property
        public static readonly DependencyProperty AllowedPixelMarginProperty =
           DependencyProperty.Register("AllowedPixelMargin", typeof(int), TriggerType,
           new PropertyMetadata(4, OnAllowedPixelMarginPropertyChanged));
        private static void OnAllowedPixelMarginPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((IntersoftGridPresenterRowMouseDoubleClickTrigger)sender).OnAllowedPixelMarginPropertyChanged(e);
        }
        protected virtual void OnAllowedPixelMarginPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
        }
        public int AllowedPixelMargin
        {
            get { return (int)GetValue(AllowedPixelMarginProperty); }
            set { SetValue(AllowedPixelMarginProperty, value); }
        }
        #endregion AllowedPixelMargin Dependency Property
        #endregion Dependency Properties
        protected override void OnAttached()
        {
            if (AssociatedObject != null)
            {
                _gridViewMouseLeftButtonUpHandler = new MouseButtonEventHandler(OnGridViewMouseLeftButtonUp);
                AssociatedObject.AddHandler(UIElement.MouseLeftButtonUpEvent, _gridViewMouseLeftButtonUpHandler, true);
            }
            base.OnAttached();      
        }
        protected override void OnDetaching()
        {
            if (AssociatedObject != null && _gridViewMouseLeftButtonUpHandler != null)
            {
                AssociatedObject.RemoveHandler(UIElement.MouseLeftButtonUpEvent, _gridViewMouseLeftButtonUpHandler);
                _gridViewMouseLeftButtonUpHandler = null;
            }
            base.OnDetaching();
        }
        private static bool IsGridViewRow(GridPresenter gridPresenter, Point mousePosition, ref object rowDataContext)
        {
            GeneralTransform gt = gridPresenter.TransformToVisual(Application.Current.RootVisual);
            Point mousePositionOffset = gt.Transform(mousePosition);
            IEnumerable<UIElement> hitElements = VisualTreeHelper.FindElementsInHostCoordinates(mousePositionOffset, gridPresenter);
            
            var gridViewRow = hitElements.OfType<GridPresenterRowElement>().FirstOrDefault();
            if (gridViewRow != null)
            {
                rowDataContext = gridViewRow.DataContext;
            }
            return gridViewRow != null;
        }
        private void OnGridViewMouseLeftButtonUp(object sender, MouseButtonEventArgs args)
        {
            DateTime currentMouseUpDateTime = DateTime.Now;
            TimeSpan timeSpanBetweenButtonUps = currentMouseUpDateTime - _lastMouseUpDateTime;
            // First Mouse Up
            if (timeSpanBetweenButtonUps > DelayBetweenClicks || _hasFirstMouseUpOccured == false)
            {
                _firstMouseUpPosition = args.GetPosition(AssociatedObject);
                _hasFirstMouseUpOccured = true;
                _lastMouseUpDateTime = DateTime.Now;
            }
            else
            {
                Point currentMousePosition = args.GetPosition(AssociatedObject);
                object rowDataContext = null;
                // Second mouse up is 
                // A.) Within specified miliseconds of first mouse up.
                // B.) Allowed pixels margin of first mouse up
                // C.) Pointer position is within a GridPresenterRowElement
                if ((Math.Abs(_firstMouseUpPosition.X - currentMousePosition.X) < AllowedPixelMargin && Math.Abs(_firstMouseUpPosition.Y - currentMousePosition.Y) < AllowedPixelMargin)
                    && IsGridViewRow(AssociatedObject, currentMousePosition, ref rowDataContext)
                    )
                {
                    InvokeActions(args);
                }
                _hasFirstMouseUpOccured = false;
            }
        }
    }

 

Here's the XAML:

<Intersoft:GridPresenter SelectedItem="{Binding MySelectedItem, Mode=TwoWay}">
	<Interactivity:Interaction.Triggers>
	    <BlendTriggers:IntersoftGridPresenterRowMouseDoubleClickTrigger>
	        <BehaviorActions:InvokeCommandAction 
                    Command="{Binding Path=TestCommand}" /> 
	    </BlendTriggers:IntersoftGridPresenterRowMouseDoubleClickTrigger>
	</Interactivity:Interaction.Triggers>
</Intersoft:GridPresenter>

 


All times are GMT -5. The time now is 12:38 AM.
Previous Next