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
ASP.NET Identity Change Password
Wait for Response from the Serial Port and Then Send Next Data
How to Count the Number of Elements That Match a Condition with Linq
Setting Culture for ASP.NET MVC Application on VS Dev Server and Iis
Restoring Window Size/Position with Multiple Monitors
Where Is My System.Numerics Namespace
Determine Client's Computer Name
JSON.Net (De)Serialize Untyped Property
Conversion of a Decimal to Double Number in C# Results in a Difference
Removing the Delay After Keydown Event
Correct Implementation of a Custom Config Section with Nested Collections
When Not to Use Yield (Return)
C# - Outputting Image to Response Output Stream Giving Gdi+ Error