Как заставить работать стандартные горячие клавиши (Ctrl+C, Ctrl+Z) в режиме редактирования DataGridView?

У меня есть простое приложение.net, содержащее вкладки и datargridview на каждой вкладке. Я добавил главное меню в форму и назначил горячие клавиши элементам меню, используя стандартное свойство:

editMenuItem = new ToolStripMenuItem("Copy", null, new System.EventHandler(onCopyCut_Click));
editMenuItem.ShortcutKeys = Keys.Control | Keys.C;

Показанный выше пункт меню просто копирует содержимое ячейки в буфер обмена. Это работает нормально, но в режиме редактирования DGV Ctrl+C и другие стандартные горячие клавиши больше не работают!

Я установил Form.KeyPreview свойство true, также пытался отключить свойство Handled моего объекта Form, но ничего не происходит:

    void FileOrginizerForm_KeyDown(object sender, KeyEventArgs e)
    {
            ...
        if (gridView.CurrentCell.IsInEditMode)
            e.Handled = false;
    }

Что мне не хватает? Я уверен, что это должно быть что-то простое.

Я нашел некоторую информацию в комментариях на странице справки msdn:

При настройке этих свойств нужно помнить одну вещь: если в вашей форме есть элемент управления textbox, ShortcutKeys пункта меню будут перехватывать эту комбинацию клавиш, и текстовое поле никогда не получит ее, например, если у вас есть вставка (ctrl + v) ShortcutKey, ваше текстовое поле никогда не получит команду вставки. По словам Microsoft, это по замыслу. Их обходной путь - временно очистить свойство ShortCutKey элемента меню, чтобы разрешить команду вставки (скорее всего, во время события), а затем сбросить его после завершения события.

РЕШЕНИЕ:

Вместо того, чтобы включать и выключать ярлыки меню, я вызывал обработчики событий меню из обработчика событий KeyDown основной формы:

    void FileOrginizerForm_KeyDown(object sender, KeyEventArgs e)
    {
        if (!gridView.CurrentCell.IsInEditMode)
        {
            if (e.KeyData == (Keys.Control | Keys.Z))
            {
                this.editToolStripMenuItem.DropDownItems["Undo"].PerformClick();
            }
            else if (e.KeyData == (Keys.Control | Keys.Y))
            {
                this.editToolStripMenuItem.DropDownItems["Redo"].PerformClick();
            }
            else if (e.KeyData == (Keys.Control | Keys.X))
            {
                    this.editToolStripMenuItem.DropDownItems["Cut"].PerformClick();
            }
            else if (e.KeyData == (Keys.Control | Keys.C))
            {
                    this.editToolStripMenuItem.DropDownItems["Copy"].PerformClick();
            }
            else if (e.KeyData == (Keys.Control | Keys.V))
            {
                    this.editToolStripMenuItem.DropDownItems["Paste"].PerformClick();
            }
            else if (e.KeyData == (Keys.Control | Keys.A))
            {

this.selectToolStripMenuItem.DropDownItems["Select All"].PerformClick();
            }
        }
    }

3 ответа

Вы можете использовать два события, показанные в демонстрации ниже, чтобы временно удалить ярлыки из пунктов вашего меню.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;

public class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public Form1()
    {
        var dgv = new DataGridView
        {
            Dock = DockStyle.Fill,
            DataSource = new List<DummyObject>
            {
                new DummyObject { Name = "One", Value = 1 },
                new DummyObject { Name = "Two", Value = 2 },
                new DummyObject { Name = "Three", Value = 3 },
            }
        };
        dgv.EditingControlShowing += (s, e) => e.Control.VisibleChanged += DgvEditingControlVisibleChanged;
        Controls.Add(dgv);
    }

    void DgvEditingControlVisibleChanged(object sender, EventArgs e)
    {
        Control control = sender as Control;
        if (control.Visible)
        {
            // The editing control has become visible.

            Trace.WriteLine(String.Format("Editing control showing {0}", control));
        }
        else
        {
            // The editing control has been removed.

            // Remove the event handler because the DGV can use multiple
            //  editing controls if it has different column types. 
            control.VisibleChanged -= DgvEditingControlVisibleChanged;
            Trace.WriteLine(String.Format("Editing control removed {0}", control));
        }
    }
}

public class DummyObject
{
    public string Name { get; set; }
    public int Value { get; set; }
}

Если вы добавите SendKeys.Send("^c"); к событию click пункта меню вам не нужно удалять ярлык из пункта меню

Просто удалите ярлык из пункта меню и поместите текст для него в текст пункта меню. Это работает для использования ярлыка на формах, но вам все равно придется кодировать, если щелкнуть сам пункт меню

Другие вопросы по тегам