Reputation: 3480
I have a DataGridView on a WinForm. When the user right-click on the grid, I am showing a popup menu. There are 3 kinds of popup menu according to where the right-click has been done:
I created a new classes to manage the popup menus generation.
public class GridPopupMenuFactory
{
public ContextMenu GetMenu(int rowIndex, bool isReadOnlyRow)
{
BaseMenu _menu = null;
switch (rowIndex)
{
case -1:
_menu = new GeneralMenu();
break;
default:
if (isReadOnlyRow)
{
_menu = new ReadonlyRowMenu();
}
else
{
_menu = new EditableRowMenu();
}
break;
}
return _menu.Menu;
}
}
public abstract class BaseMenu
{
protected ContextMenu _menu;
public ContextMenu Menu
{
get
{
if (_menu.MenuItems.Count == 0)
{
GenerateMenu();
}
return _menu;
}
}
protected abstract void GenerateMenu();
}
public class GeneralMenu : BaseMenu
{
protected override void GenerateMenu()
{
var contextMenu = new ContextMenu();
contextMenu.MenuItems.Add(new MenuItem("Sort"));
contextMenu.MenuItems.Add(new MenuItem("Print"));
_menu = contextMenu;
}
}
public class ReadonlyRowMenu : BaseMenu
{
protected override void GenerateMenu()
{
var contextMenu = new ContextMenu();
contextMenu.MenuItems.Add(new MenuItem("View"));
_menu = contextMenu;
}
}
public class EditableRowMenu : BaseMenu
{
protected override void GenerateMenu()
{
var contextMenu = new ContextMenu();
contextMenu.MenuItems.Add(new MenuItem("Add"));
contextMenu.MenuItems.Add(new MenuItem("Edit"));
contextMenu.MenuItems.Add(new MenuItem("Delete"));
_menu = contextMenu;
}
}
// Winform
private void shipmentDetailsDataGridView_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
var rowIndex = shipmentDetailsDataGridView.HitTest(e.X, e.Y).RowIndex;
var popupMenu = GridPopupMenu.GetMenu(rowIndex, false); // 2nd parameter can be true, TODO
popupMenu.Show(shipmentDetailsDataGridView, new Point(e.X, e.Y));
}
}
My question is where is the correct place to define the event handler for each one of the menu items?
Update: After clicking on the menu item, the whole operation is done on the DataGridView itself. For example, clicking on add, will open a temp form with all the required field and then this information will be added as a new row in the DataGridView.
Upvotes: 0
Views: 76
Reputation: 17850
I believe it should looks like this:
public class GeneralMenu : BaseMenu {
protected override void GenerateMenu() {
var contextMenu = new ContextMenu();
contextMenu.MenuItems.Add(new MenuItem("Sort", OnSort));
contextMenu.MenuItems.Add(new MenuItem("Print", OnPrint));
_menu = contextMenu;
}
void OnSort(object sender, EventArgs e) {
var gridView = GetSourceControl<DataGridView>(sender);
if(gridView != null) {
// do sort
}
}
void OnPrint(object sender, EventArgs e) {
var gridView = GetSourceControl<DataGridView>(sender);
if(gridView != null) {
// do print
}
}
static TControl GetSourceControl<TControl>(object sender) where TControl : Control {
var menu = ((MenuItem)sender).GetContextMenu();
return (menu != null) ? menu.SourceControl as TControl : null;
}
}
Upvotes: 1