/// <summary>
        /// Executes a context menu command.
        /// </summary>
        /// <param name="cmd"><see cref="ContextMenuCommands"/> that specifies which
        /// command should be executed.</param>
        public void ExecuteCommand(ContextMenuCommands cmd)
        {
            // save selection
            var sel = _grid.Selection;

            // execute command
            IUndoableAction action;

            switch (cmd)
            {
            case ContextMenuCommands.Cut:
                _grid.Copy();
                _grid.ClearSelection();
                break;

            case ContextMenuCommands.Copy:
                _grid.Copy();
                break;

            case ContextMenuCommands.Paste:
                _grid.Paste();
                break;

            case ContextMenuCommands.Clear:
                _grid.ClearSelection();
                break;

            case ContextMenuCommands.InsertRows:
                if (sel.IsValid)
                {
                    // to clone styles from row above (like Excel)
                    var index    = sel.TopRow > 0 ? sel.TopRow - 1 : sel.TopRow;
                    var styleRow = _grid.Rows[index] as ExcelRow;

                    action = new InsertDeleteRowAction(_grid);
                    for (int i = 0; i < sel.RowSpan; i++)
                    {
                        _grid.Rows.Insert(sel.TopRow, new ExcelRow(styleRow));
                    }
                    if (action.SaveNewState())
                    {
                        _grid.UndoStack.AddAction(action);
                    }
                }
                else
                {
                    action = new InsertDeleteRowAction(_grid);
                    _grid.Rows.Add(new ExcelRow());
                    if (action.SaveNewState())
                    {
                        _grid.UndoStack.AddAction(action);
                    }
                }
                break;

            case ContextMenuCommands.DeleteRows:
                if (sel.IsValid)
                {
                    action = new InsertDeleteRowAction(_grid);
                    for (int i = 0; i < sel.RowSpan; i++)
                    {
                        _grid.Rows.RemoveAt(sel.TopRow);
                    }
                    if (action.SaveNewState())
                    {
                        _grid.UndoStack.AddAction(action);
                    }
                }
                break;

            case ContextMenuCommands.InsertColumns:
                if (sel.IsValid)
                {
                    action = new InsertDeleteColumnAction(_grid);
                    for (int i = 0; i < sel.ColumnSpan; i++)
                    {
                        _grid.Columns.Insert(sel.LeftColumn, new Column());
                    }
                    if (action.SaveNewState())
                    {
                        _grid.UndoStack.AddAction(action);
                    }
                }
                else
                {
                    action = new InsertDeleteColumnAction(_grid);
                    _grid.Columns.Add(new Column());
                    if (action.SaveNewState())
                    {
                        _grid.UndoStack.AddAction(action);
                    }
                }
                break;

            case ContextMenuCommands.DeleteColumns:
                if (sel.IsValid)
                {
                    action = new InsertDeleteColumnAction(_grid);
                    for (int i = 0; i < sel.ColumnSpan; i++)
                    {
                        _grid.Columns.RemoveAt(sel.LeftColumn);
                    }
                    if (action.SaveNewState())
                    {
                        _grid.UndoStack.AddAction(action);
                    }
                }
                break;
            }

            // restore selection
            try
            {
                _grid.Focus();
                _grid.Selection = sel;
            }
            catch
            {
                // old selection became invalid after deleting rows/columns
            }
        }
        /// <summary>
        /// Executes a context menu command.
        /// </summary>
        /// <param name="cmd"><see cref="ContextMenuCommands"/> that specifies which 
        /// command should be executed.</param>
        public void ExecuteCommand(ContextMenuCommands cmd)
        {
            // save selection
            var sel = _grid.Selection;

            // execute command
            IUndoableAction action;
            switch (cmd)
            {
                case ContextMenuCommands.Cut:
                    _grid.Copy();
                    _grid.ClearSelection();
                    break;

                case ContextMenuCommands.Copy:
                    _grid.Copy();
                    break;

                case ContextMenuCommands.Paste:
                    _grid.Paste();
                    break;

                case ContextMenuCommands.Clear:
                    _grid.ClearSelection();
                    break;

                case ContextMenuCommands.InsertRows:
                    if (sel.IsValid)
                    {
                        // to clone styles from row above (like Excel)
                        var index = sel.TopRow > 0 ? sel.TopRow - 1 : sel.TopRow;
                        var styleRow = _grid.Rows[index] as ExcelRow;

                        action = new InsertDeleteRowAction(_grid);
                        for (int i = 0; i < sel.RowSpan; i++)
                        {
                            _grid.Rows.Insert(sel.TopRow, new ExcelRow(styleRow));
                        }
                        if (action.SaveNewState())
                        {
                            _grid.UndoStack.AddAction(action);
                        }
                    }
                    else
                    {
                        action = new InsertDeleteRowAction(_grid);
                        _grid.Rows.Add(new ExcelRow());
                        if (action.SaveNewState())
                        {
                            _grid.UndoStack.AddAction(action);
                        }
                    }
                    break;

                case ContextMenuCommands.DeleteRows:
                    if (sel.IsValid)
                    {
                        action = new InsertDeleteRowAction(_grid);
                        for (int i = 0; i < sel.RowSpan; i++)
                        {
                            _grid.Rows.RemoveAt(sel.TopRow);
                        }
                        if (action.SaveNewState())
                        {
                            _grid.UndoStack.AddAction(action);
                        }
                    }
                    break;

                case ContextMenuCommands.InsertColumns:
                    if (sel.IsValid)
                    {
                        action = new InsertDeleteColumnAction(_grid);
                        for (int i = 0; i < sel.ColumnSpan; i++)
                        {
                            _grid.Columns.Insert(sel.LeftColumn, new Column());
                        }
                        if (action.SaveNewState())
                        {
                            _grid.UndoStack.AddAction(action);
                        }
                    }
                    else
                    {
                        action = new InsertDeleteColumnAction(_grid);
                        _grid.Columns.Add(new Column());
                        if (action.SaveNewState())
                        {
                            _grid.UndoStack.AddAction(action);
                        }
                    }
                    break;

                case ContextMenuCommands.DeleteColumns:
                    if (sel.IsValid)
                    {
                        action = new InsertDeleteColumnAction(_grid);
                        for (int i = 0; i < sel.ColumnSpan; i++)
                        {
                            _grid.Columns.RemoveAt(sel.LeftColumn);
                        }
                        if (action.SaveNewState())
                        {
                            _grid.UndoStack.AddAction(action);
                        }
                    }
                    break;
            }

            // restore selection
            try
            {
                _grid.Focus();
                _grid.Selection = sel;
            }
            catch
            {
                // old selection became invalid after deleting rows/columns
            }
        }