Determine what control the ContextMenuStrip was used on - c#

I have a ContextMenuStrip that is assigned to several different listboxes. I am trying to figure out when the ContextMenuStrip is clicked what ListBox it was used on. I tried the code below as a start but it is not working. The sender has the correct value, but when I try to assign it to the menuSubmitted it is null.
private void MenuViewDetails_Click(object sender, EventArgs e)
{
ContextMenu menuSubmitted = sender as ContextMenu;
if (menuSubmitted != null)
{
Control sourceControl = menuSubmitted.SourceControl;
}
}
Any help would be great. Thanks.
Using the assistance below, I figured it out:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
if (menuItem != null)
{
ContextMenuStrip calendarMenu = menuItem.Owner as ContextMenuStrip;
if (calendarMenu != null)
{
Control controlSelected = calendarMenu.SourceControl;
}
}
}

For a ContextMenu:
The problem is that the sender parameter points to the item on the context menu that was clicked, not the context menu itself.
It's a simple fix, though, because each MenuItem exposes a GetContextMenu method that will tell you which ContextMenu contains that menu item.
Change your code to the following:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a MenuItem
MenuItem menuItem = sender as MenuItem;
if (menuItem != null)
{
// Retrieve the ContextMenu that contains this MenuItem
ContextMenu menu = menuItem.GetContextMenu();
// Get the control that is displaying this context menu
Control sourceControl = menu.SourceControl;
}
}
For a ContextMenuStrip:
It does change things slightly if you use a ContextMenuStrip instead of a ContextMenu. The two controls are not related to one another, and an instance of one cannot be casted to an instance of the other.
As before, the item that was clicked is still returned in the sender parameter, so you will have to determine the ContextMenuStrip that owns this individual menu item. You do that with the Owner property. Finally, you'll use the SourceControl property to determine which control is displaying the context menu.
Modify your code like so:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a ToolStripItem
ToolStripItem menuItem = sender as ToolStripItem;
if (menuItem != null)
{
// Retrieve the ContextMenuStrip that owns this ToolStripItem
ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;
if (owner != null)
{
// Get the control that is displaying this context menu
Control sourceControl = owner.SourceControl;
}
}
}

Older post, but in case someone like myself comes across it:
For a ContextMenuStrip, the above didn't work for me, but it led to finding what did.
void DeleteMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
Control sourceControl = menu.SourceControl;
MessageBox.Show(sourceControl.Name);
}
This gave me the expected control's name. You can put in validation etc with if statements, I'm just posting to get to the point.

I had great difficulty getting any of this code to work. This is the simplest solution I could find:
For A ContextMenuStrip:
Control _sourceControl = null;
private void contextMenuStrip_Opened(object sender, EventArgs e)
{
_sourceControl = contextMenuStrip.SourceControl;
}
private void contextMenuItem_Click(object sender, EventArgs e)
{
var menuItem = (ToolStripMenuItem)sender;
_sourceControl.Text = menuItem.Text;
MessageBox.Show(menuItem.Name);
MessageBox.Show(sourceControl.Name);
}

Cast sender to ToolStripItem to reach Owner which will be a ToolStrip that doesn't have a SourceControl property.
Cast Owner to ContextMenuStrip to reach SourceControl.
Control sc = ((ContextMenuStrip)((ToolStripItem)sender).Owner).SourceControl;

How about just using ActiveForm.ActiveControl, in this example from a C1 grid:
C1.Win.FlexGrid.C1FlexGrid fg = frmMain.ActiveForm.ActiveControl as C1.Win.FlexGrid.C1FlexGrid;

The easiest solution would be:
Control parentControl = ((sender as MenuItem).GetContextMenu()).SourceControl;

Related

C# WPF System.Windows.Controls.TreeView how to change selected node

This treeview class works differently from the windows forms class. Every example I see to change selected node uses items.selectednode or nodes.selectednode.
However, I am struggling to find a method of doing this for this class:
https://msdn.microsoft.com/en-us/library/system.windows.controls.treeview(v=vs.110).aspx
I wanted to enable right click to popup my context menu. Could not find another solution, so here's what I did, and it works:
private void TreeSetup_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
((TreeViewItem)sender).IsSelected = true;
e.Handled = true;
}
private void TreeSetup_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
ContextMenu PopupMenu = this.FindResource("cmButton") as ContextMenu;
if (TreeSetup.SelectedItem != null)
{
PopupMenu.PlacementTarget = sender as TreeViewItem;
PopupMenu.IsOpen = true;
}
}

Trying to get the SourceControl of a ContextMenuStrip [duplicate]

I have a ContextMenuStrip that is assigned to several different listboxes. I am trying to figure out when the ContextMenuStrip is clicked what ListBox it was used on. I tried the code below as a start but it is not working. The sender has the correct value, but when I try to assign it to the menuSubmitted it is null.
private void MenuViewDetails_Click(object sender, EventArgs e)
{
ContextMenu menuSubmitted = sender as ContextMenu;
if (menuSubmitted != null)
{
Control sourceControl = menuSubmitted.SourceControl;
}
}
Any help would be great. Thanks.
Using the assistance below, I figured it out:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
if (menuItem != null)
{
ContextMenuStrip calendarMenu = menuItem.Owner as ContextMenuStrip;
if (calendarMenu != null)
{
Control controlSelected = calendarMenu.SourceControl;
}
}
}
For a ContextMenu:
The problem is that the sender parameter points to the item on the context menu that was clicked, not the context menu itself.
It's a simple fix, though, because each MenuItem exposes a GetContextMenu method that will tell you which ContextMenu contains that menu item.
Change your code to the following:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a MenuItem
MenuItem menuItem = sender as MenuItem;
if (menuItem != null)
{
// Retrieve the ContextMenu that contains this MenuItem
ContextMenu menu = menuItem.GetContextMenu();
// Get the control that is displaying this context menu
Control sourceControl = menu.SourceControl;
}
}
For a ContextMenuStrip:
It does change things slightly if you use a ContextMenuStrip instead of a ContextMenu. The two controls are not related to one another, and an instance of one cannot be casted to an instance of the other.
As before, the item that was clicked is still returned in the sender parameter, so you will have to determine the ContextMenuStrip that owns this individual menu item. You do that with the Owner property. Finally, you'll use the SourceControl property to determine which control is displaying the context menu.
Modify your code like so:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a ToolStripItem
ToolStripItem menuItem = sender as ToolStripItem;
if (menuItem != null)
{
// Retrieve the ContextMenuStrip that owns this ToolStripItem
ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;
if (owner != null)
{
// Get the control that is displaying this context menu
Control sourceControl = owner.SourceControl;
}
}
}
Older post, but in case someone like myself comes across it:
For a ContextMenuStrip, the above didn't work for me, but it led to finding what did.
void DeleteMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
Control sourceControl = menu.SourceControl;
MessageBox.Show(sourceControl.Name);
}
This gave me the expected control's name. You can put in validation etc with if statements, I'm just posting to get to the point.
I had great difficulty getting any of this code to work. This is the simplest solution I could find:
For A ContextMenuStrip:
Control _sourceControl = null;
private void contextMenuStrip_Opened(object sender, EventArgs e)
{
_sourceControl = contextMenuStrip.SourceControl;
}
private void contextMenuItem_Click(object sender, EventArgs e)
{
var menuItem = (ToolStripMenuItem)sender;
_sourceControl.Text = menuItem.Text;
MessageBox.Show(menuItem.Name);
MessageBox.Show(sourceControl.Name);
}
Cast sender to ToolStripItem to reach Owner which will be a ToolStrip that doesn't have a SourceControl property.
Cast Owner to ContextMenuStrip to reach SourceControl.
Control sc = ((ContextMenuStrip)((ToolStripItem)sender).Owner).SourceControl;
How about just using ActiveForm.ActiveControl, in this example from a C1 grid:
C1.Win.FlexGrid.C1FlexGrid fg = frmMain.ActiveForm.ActiveControl as C1.Win.FlexGrid.C1FlexGrid;
The easiest solution would be:
Control parentControl = ((sender as MenuItem).GetContextMenu()).SourceControl;

Get sender's element type (Button, PictureBox etc..)

I am using a void for multiple elements. Such as buttons, labels, pictureboxes....
But i need to modify some of the sender's variables. Such as name, top, left etc... This is my code:
private void FareSurukle(object sender, MouseEventArgs e)
{
MessageBox.Show(((TYPE_COMES_HERE)sender).Name);
}
If i edit "TYPE_COMES_HERE" to PictureBox, it works on PictureBox. But it gives error on other elements. Like buttons.
Is it possible to get and modify sender's variables without declaring it's type? Or can i make a type check of sender with if's?
I need to modify some of the sender's properties, such as name, top, left
You don't have to inspect the exact type for that. The controls you mention all inherit from a base class that contains all these properties, aptly named Control:
MessageBox.Show(((Control)sender).Name);
You can try casting to each type and do something with it if not null:
var button = sender as Button;
if (button != null)
{
// do something with button
}
var pictureBox = sender as PictureBox;
if (pictureBox != null)
{
// do something with pictureBox
}
private void FareSurukle(object sender, MouseEventArgs e)
{
if (sender is PictureBox)
{
// do something
}
else if (sender is Label)
{
// do something
}
else if (sender is Button)
{
// do something
}
}

Drag/Drop Label onto FlowLayoutPanel

Im trying to drag a label from a FlowLayoutPanel to another FlowLayoutPanel.Im able to drag but it wont drop the label?
My Code
private void flp_DragEnter(object sender, DragEventArgs e)
{
if ((e.AllowedEffect & DragDropEffects.Link) != 0
&& e.Data.GetDataPresent(typeof(string)))
e.Effect = DragDropEffects.Link;
}
private void flp_DragDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(Label)))
{
FlowLayoutPanel destination = (FlowLayoutPanel)sender;
Control control = (Control)e.Data.GetData(typeof(Label));
destination.Controls.Add(control);
return;
}
}
private void lbl_MouseDown(object sender, MouseEventArgs e)
{
DoDragDrop((sender as Label).Text, DragDropEffects.Link);
}
You can set the Name of the controls as drag data, and then when dropping, find the control by name and remove it from its parent controls collection and add it to target panel controls collection. To do so:
Set AllowDrop property for each control that is target of drop. The target controls in your example can be both FlowLayoutPanel controls.
Handle MouseDown event for each control that drag starts with it and in the handler call DoDragDrop event of that control and set the data that you want to drag. The moving controls in your example are labels and the data here can be Name of control.
Handle DragEnetr event of each target of drag and set e.Effect to determine if drop is allowed or not. Here is the place that you can check if drop is allowed. For example you can check if the data is string and the string is the name of a control.
Hanlde DragDrop and use GetData method of e.Data to get the data and perform the actions when drop. The action here is removing the control from its current parent and add it to the new parent.
Code:
Using the below code, if you assign control_MouseDown to MouseDown events of all labels and assign panel_DragEnter to DragEnter event of both flow layout panels and also assign panel_DragDrop to DragDrop event of both flow layout panels, you can move labels between both flow layout panels, also you can re order labels in a panel:
private void control_MouseDown(object sender, MouseEventArgs e)
{
var control = sender as Control;
this.DoDragDrop(control.Name, DragDropEffects.Move);
}
private void panel_DragEnter(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(string)))
return;
var name = e.Data.GetData(typeof(string)) as string;
var control = this.Controls.Find(name, true).FirstOrDefault();
if (control != null)
{
e.Effect = DragDropEffects.Move;
}
}
private void panel_DragDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(string)))
return;
var name = e.Data.GetData(typeof(string)) as string;
var control = this.Controls.Find(name, true).FirstOrDefault();
if (control != null)
{
control.Parent.Controls.Remove(control);
var panel = sender as FlowLayoutPanel;
((FlowLayoutPanel)sender).Controls.Add(control);
}
}

Which object was the chosen option from ContextMenuStrip

I make windows form application. I have on form TreeView, I add few nodes and add ContextMenuStrip.
var menu = new ContextMenuStrip();
menu.Items.Add("Some text", new Bitmap(1, 1), new EventHandler(function_name));
var treeView = new TreeView(..);
treeView.ContextMenuStrip = menu;
treeView.Nodes.Add(new TreeNode()
{
...
Tag = someObject
});
My problems is how can I check in function function_name on which treeNode was clicked and chosen option from ContextMenuStrip
edit
function_name sygnature
public void pokaz_DoubleClick(object sender, EventArgs e)
{
}
You can handle the TreeNodeMouseClick event. In your TreeNodeMouseClickEventHandler you will have access to a TreeNodeMouseClickEventArgs argument. This argument contains a number of properties you can use to check which mouse button was clicked on which node. For example.
private TreeNode rightClickeNode;
void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
rightClickedNode = e.Node;
}
}
You can then access rightClickedNode from your function_name.
what is the signature of the function_name method?
generally you can check the content of the sender parameter but it could happen it is the TreeView and not the TreeNode, if so you can check the properties of the e parameter.
Another way is that at every mouse down you make sure you select the node under the mouse in the TreeView so when function_name executes you get your node taking treeview.SelectedNode
You can make the node selected right before the Context Menu is shown and then you just need to check the SelectedNode property. Something like this:
private void treeView_MouseDown(object sender, MouseEventArgs e)
{
//See what node is at the location that was just clicked
var clickedNode = treeView.GetNodeAt(e.Location);
//Make that node the selected node
treeView.SelectedNode = clickedNode;
}
private void function_name(object sender, EventArgs e)
{
var currentNode = treeView.SelectedNode;
//Do something with currentNode
}

Categories

Resources