Silverlight data grid extensions

Data Grid Ex Support two new events

  • Commit (An event that indicates that a selection is complete and has been made, effectively commit action.)
  • Cancel (An event that indicates that the selection operation has been canceled)

Also supports single row double click.

Event Commit will be raise if user double click on row or press enter while row is selected where as event Cancel is fired if user click on Esc button.

Class DataGridEx :

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.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Automation.Peers;
using System.Linq;

namespace XXX.YYY.Controls
{
    public class DataGridEx : DataGrid
    {
        private DataGridRow _LastDataGridRow = null;
        private DataGridColumn _LastDataGridColumn = null;
        private DataGridCell _LastDataGridCell = null;
        private object _LastObject = null;
        private DateTime _LastClick = DateTime.MinValue;

        private double _DoubleClickTime = 1500;

        /// 
        /// An event that indicates that a selection is complete and has been
        /// made, effectively a commit action.
        /// 
        public event RoutedEventHandler Commit;

        /// 
        /// An event that indicates that the selection operation has been
        /// canceled.
        /// 
        public event RoutedEventHandler Cancel;

        /// 
        /// Initializes a new instance of the DataGridEx class.
        /// 
        public DataGridEx()
        {
            MouseLeftButtonUp += OnGridMouseLeftButtonUp;
        }

        private void OnGridMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            DateTime clickTime = DateTime.Now;
            DataGridRow currentRowClicked;
            DataGridColumn currentColumnClicked;
            DataGridCell currentCellClicked;
            object currentObject;

            //If we've found at least the row,
            if (GetDataGridCellByPosition(e.GetPosition(null), out currentRowClicked, out currentColumnClicked, out currentCellClicked, out currentObject))
            {
                //And the current row is the same as the last row, and is within the timespan, consider it a double-click
                bool isDoubleClick = (currentRowClicked == _LastDataGridRow && clickTime.Subtract(_LastClick) <= TimeSpan.FromMilliseconds(_DoubleClickTime));

                _LastDataGridRow = currentRowClicked;
                _LastDataGridColumn = currentColumnClicked;
                _LastDataGridCell = currentCellClicked;
                _LastObject = currentObject;

                if (isDoubleClick)
                {
                    OnItemDoubleClick(this,null);
                }
            }
            else
            {
                _LastDataGridRow = null;
                _LastDataGridCell = null;
                _LastDataGridColumn = null;
                _LastObject = null;
            }

            _LastClick = clickTime;

        }

        private bool GetDataGridCellByPosition(Point pt, out DataGridRow dataGridRow, out DataGridColumn dataGridColumn, out DataGridCell dataGridCell, out object dataGridObject)
        {
            var elements = VisualTreeHelper.FindElementsInHostCoordinates(pt, this);
            dataGridRow = null;
            dataGridCell = null;
            dataGridColumn = null;
            dataGridObject = null;

            if (null == elements || elements.Count() == 0)
            {
                return false;
            }

            var rowQuery = from gridRow in elements where gridRow is DataGridRow select gridRow as DataGridRow;
            dataGridRow = rowQuery.FirstOrDefault();
            if (dataGridRow == null)
            {
                return false;
            }

            dataGridObject = dataGridRow.DataContext;

            var cellQuery = from gridCell in elements where gridCell is DataGridCell select gridCell as DataGridCell;
            dataGridCell = cellQuery.FirstOrDefault();

            if (dataGridCell != null)
            {
                dataGridColumn = DataGridColumn.GetColumnContainingElement(dataGridCell);
            }

            //If we've got the row, return true - sometimes the Column, DataContext could be null
            return dataGridRow != null;
        }

        private void OnItemDoubleClick(object sender,RoutedEventArgs e)
        {
             OnCommit(this, e);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            HandleKeyDown(e);
            if (!e.Handled)
                base.OnKeyDown(e);
        }

        /// 
        /// Process a key down event.
        /// 
        /// The key event arguments object.
        public void HandleKeyDown(KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Enter:
                    OnCommit(this, e);
                    e.Handled = true;
                    break;

                case Key.Escape:
                    OnCancel(this, e);
                    e.Handled = true;
                    break;

                default:
                    break;
            }
        }

        /// 
        /// Fires the Commit event.
        /// 
        /// The source object.
        /// The event data.
        private void OnCommit(object sender, RoutedEventArgs e)
        {
            RoutedEventHandler handler = Commit;
            if (handler != null)
            {
                handler(sender, e);
            }
        }

        /// 
        /// Fires the Cancel event.
        /// 
        /// The source object.
        /// The event data.
        private void OnCancel(object sender, RoutedEventArgs e)
        {
            RoutedEventHandler handler = Cancel;
            if (handler != null)
            {
                handler(sender, e);
            }
        }

        /// 
        /// Initializes a new instance of a DataGridAutomationPeer.
        /// 
        /// Returns a new DataGridAutomationPeer.
        public AutomationPeer CreateAutomationPeer()
        {
            return new DataGridAutomationPeer(this);
        }

    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s