Как заставить работать стандартные горячие клавиши (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 пункта меню вам не нужно удалять ярлык из пункта меню
Просто удалите ярлык из пункта меню и поместите текст для него в текст пункта меню. Это работает для использования ярлыка на формах, но вам все равно придется кодировать, если щелкнуть сам пункт меню