Get the Sourcecontrol of a Dropdownmenu

Get the SourceControl of a DropDownMenu

The ContextMenuStrip SourceControl (the reference of the current Control where the Context Menu is activated) can be retrieved, from a ToolStripMenuItem, inspecting the OwnerItem reference and moving upstream until the OwnerItem reference is null, then inspecting the Owner value, which references the ContextMenuStrip.

(Unfortunately, the SourceControl reference is only available in the ContextMenuStrip control).

A simple alternative method is using a Field that references the Control where the current ContextMenuStrip has been activated (you can have just one active ContextMenuStrip).

This Field reference, set when the ContextMenuStrip is opened - by subscribing to the Opened() event - can then be accessed by any of the ToolStripMenuItem.

The Field reference is then set back to null when then ContextMenuStrip is closed.

▶ Dispose of the contextMenuOwner object when the Form closes.

An example:

(toolStripMenuItem is a generic name, it must be set to an actual control name).

Control contextMenuOwner = null;

private void toolStripMenuItem_Click(object sender, EventArgs e)
{
contextMenuOwner?.BackColor = Color.Blue;
//(...)
}

private void contextMenuStrip1_Opened(object sender, EventArgs e)
{
contextMenuOwner = (sender as ContextMenuStrip).SourceControl;
}

private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
contextMenuOwner = null;
}

SourceControl of ContextMenuStrip is Nothing in ToolStripMenuItem Click?

I found a workaround that is not really the answer to the question. So I will leave it open for a while.

I used the ContextMenuStrip Opening event to store locally the source object.

Private Sub contextGrid_Opening(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles contextGrid.Opening

_ContextSourceGrid = DirectCast(contextGrid.SourceControl, DataGridView)

End Sub

and refer directly to the saved object inside all ToolStripMenuItem Click events.

C# how to get referece to ContextMenuStrip from underlying sub menuitems of at least two levels

You need a backward loop to get the first OwnerItem property of a given ToolStripItem (or one of the derived classes) in a branch then you can get the main ToolStrip (which can be a ToolStrip, MenuStrip, StatusStrip, or ContextMenuStrip control) through the ToolStripItem.Owner property.

Consider the following extension methods:

public static ToolStripExtensions
{
public static ToolStrip GetMainToolStrip(this ToolStripItem tsi)
{
if (tsi == null) return null;
if (tsi.OwnerItem == null) return tsi.Owner;

var oi = tsi.OwnerItem;

while (oi.OwnerItem != null) oi = oi.OwnerItem;

return oi.Owner;
}

public static ToolStrip GetMainToolStrip(this ToolStrip ts)
{
ToolStrip res = ts;

var m = ts as ToolStripDropDownMenu;

if (m?.OwnerItem != null)
res = GetMainToolStrip(m.OwnerItem);

return res;
}
}

Here's an example that shows how to get the ContextMenuStrip.SourceControl in the ItemClicked event:

private void cmnu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
if (e.ClickedItem.GetMainToolStrip() is ContextMenuStrip cmnu)
Console.WriteLine(cmnu.SourceControl.Name);
}


Related Topics



Leave a reply



Submit