BenG
BenG

Reputation: 53

How to decide where the click event was triggered

On a windows form I've got PictureBoxes, each with a StripMenu item. The PictureBoxes are in a separate class. When the user clicks on a StripMenuItem, how can I decide which PictureBox was clicked on?

I've seen posts about doing something with the sender, but I can not see anything related to the clicked item among the properties.

Here's basic my code:

    public Form1()
    {
        InitializeComponent();

        ContextMenu cm = new ContextMenu();
        MenuItem mi = new MenuItem()
        {
            Text = "click me"
        };
        mi.Click += new EventHandler(mi_Click);
        cm.MenuItems.Add(mi);


        Data d1 = new Data();
        d1.px.Location = new Point(30, 30);
        d1.px.ContextMenu = cm;

        Data d2 = new Data();
        d2.px.Location = new Point(100, 100);
        d2.px.ContextMenu = cm;

        Controls.Add(d1.px);
        Controls.Add(d2.px);

    }

    void mi_Click(object sender, EventArgs e)
    {
        var s = sender;
    }
    class Data
    {
        public PictureBox px = new PictureBox
        {
            Size = new Size(40, 40),
            BackColor = Color.Red
        };
    }

Sorry if this question was already asked but I don't know how to search for an answer.

Thanks in advance

Upvotes: 2

Views: 157

Answers (3)

BenG
BenG

Reputation: 53

I found a solution, it's nearly the same as marc_s's, so I accepted his answer.

ContextMenu cm = new ContextMenu();
MenuItem mi = new MenuItem()
{
    Text = "click me"
};
mi.Click += new EventHandler(mi_Click);
cm.MenuItems.Add(mi);
cm.Name = "name";


void tsi_Click(object sender, EventArgs e)
{
    ToolStripItem item = (sender as ToolStripItem);
    if (item != null)
    {
        ContextMenuStrip owner = item.Owner as ContextMenuStrip;
        if (owner != null)
        {
             string a = owner.Name;
        }
    }
}

Upvotes: 0

Mesko
Mesko

Reputation: 21

You can get the parent of the ContextMenuStrip by following code

private void testClickToolStripMenuItem_Click(object sender, EventArgs e)
{
    ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
    if (menuItem != null)
    {
        ContextMenuStrip menu = menuItem.Owner as ContextMenuStrip;
        if (menu != null)
        {
            // dataElement is your Data for which ContextMenu was opened
            PictureBox dataElement = menu.SourceControl as PictureBox;
        }
    }
}

EDIT: You can also make your own UserControl and use it instead of Data. In your example Data only has PictureBox in it. If PictureBox is actually your data Object you can do it like this:

public class Data : PictureBox
{
    public Data() : base()
    {
        this.Size = new Size(40,40);
        this.BackColor = Color.Red;
    }
}

Then your Data Object is descendant of Control object and you can bind ContextMenu to it and even you should be able to get it with this code:

Data dataElement = menu.SourceControl as Data;

Upvotes: 1

marc_s
marc_s

Reputation: 755411

It's been a while since I did any Winforms coding - but you might be able to find out which control caused the click with this code:

void mi_Click(object sender, EventArgs e)
{
    // try to convert your "sender" to a ToolStripItem
    ToolStripItem item = (sender as ToolStripItem);

    if (item != null) 
    {
        // if successful - get the MenuItem's "Parent" -> that should be your "ContextMenu"
        ContextMenuStrip ctxMenu = item.Owner as ContextMenuStrip;

        if(ctxMenu != null)
        {
            // if that's successful, the context menu's "SourceControl"
            // should tell you which control the menu was opened over 
            Control controlThatCausedMenuItemToBeClicked = ctxMenu.SourceControl;
            string controlsName = controlThatCausedMenuItemToBeClicked.Name;
        }
    }
}

Update: @Mesko got the class names for ToolStripItem and ContextMenuStrip right - I was a bit rusty and didn't know those by heart any more - updated my post, with thanks to @Mesko.

But at the last step, you get back the control that the context menu was opened over, and the menu item was clicked over. This is a "generic" control, but you can always get the .Name of the control and then keep the various PictureBoxes apart based on their name.

Upvotes: 1

Related Questions