ContextMenu on disabled controls such as buttons - c#

I'm looking for a way to enable/disable buttons using theirContextMenu. But my problem is when I click on the Enable MenuItem to disable the button the ContextMenu won't show anymore.
Is there a way to keep the ContextMenu or other behavior on a disabled Control?
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("Enable", new EventHandler(enableButton));
this.button1.ContextMenu = cm;
private void enableButton(object sender, EventArgs e)
{
MenuItem menuItem = sender as MenuItem;
if (menuItem != null)
{
ContextMenu menu = menuItem.GetContextMenu();
Control sourceControl = menu.SourceControl;
sourceControl.Enabled = !sourceControl.Enabled;
}
}

Make your own disabling functionality, set the buttons to grayed out, intercept their events, this way the button will appear disabled but be enabled to receive the ContextMenu event. This behaviour is "By-Design".
You can easily work out the btn.Font to look disabled. For the events one way is to unsubscribe them on Disable, and Hook them up on Enable, here is an example on getting a controls events...
dynamic controltype = btn;
var events = Type.ReflectionOnlyGetType(controltype.AssemblyQualifiedName, false, true).GetEvents();
foreach (var item in events)
{
//EventHandler<T> use a generic Event Handler to Subscribe and Unsubscribe
}

From MSDN
With the Enabled property, you can enable or disable controls at run
time. For example, you can disable controls that do not apply to the
current state of the application. You can also disable a control to
restrict its use. For example, a button can be disabled to prevent the
user from clicking it. If a control is disabled, it cannot be
selected.
and
When a container control has its enabled property set to false, all
its contained controls are disabled, as well. For example, if the user
clicks on any of the controls contained in a disabled GroupBox
control, no events are raised.
So, disabled control cannot raise any events.
You can make your own disable method which make button gayed and disable click events, and reverse enable method.
Based on #esiprogrammer sugestion you can do something like this:
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Point pt = e.Location;
Control ctrl = this.GetChildAtPoint(pt);
if (ctrl != null)
{
ContextMenu menu = ctrl.ContextMenu;
menu.Show(ctrl, new Point(10,10));
}
}
}

there is a workaround to detect right click on mouse up event of form and show context menu. and using this.GetChildAtPoint(e.Location) you can find which control you right clicked on.
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right
&& this.GetChildAtPoint(e.Location)?.Name == "enableButton")
{
ContextMenu.Show();
}
}

Related

Annoying Border around button when pressing tab and clicking a button

I get this very annoying border when pressing tab and the clicking the button
I've tried
foreach (Control x in this.Controls)
{
if (x is Button)
{
Button newbut = (Button)x;
newbut.FlatStyle = FlatStyle.Flat;
newbut.FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
newbut.FlatAppearance.BorderSize = 0;
newbut.TabStop = false;
}
}
And I've also tried doing adding an event on Keydown and not allowing to press the tab key but nothing has worked so far.
this is example of the border that keeps popping up
Fixed by generating own button class and editing the designer.cs file
If you do not want custom buttons, you can shift focus to another control once finished, this prevents the rectangle from showing. You could place a dummy control out of view and shift fucus to this.
private void btnDoSomething_Click(object sender, EventArgs e)
{
myDummyControl.Focus();
MessageBox.Show("This still executes even though we have lost focus");
// If you are decoupling your code from the UI, this becomes second nature quickly as it becomes part of your control handling.
}
Also you can stop the control from getting Tab focus my setting it's TabStop property tp false, do this in the buttons Paint event.
If you have many buttons, you can just point them to the same event handler (On_Paint).
private void On_Paint(object sender, PaintEventArgs e)
{
Button thisButton = sender as Button;
thisButton.TabStop = false;
}

How to find in what Panel my button is placed in?

I have some questions that are situated in distinct panels. I place button "Add" in every panel. This button is supposed to add additional textbox to panel. But I don't know what to write in button_click. What panel to choose?
private void button_Click(object sender, EventArgs e)
{
}
Use Control.Parent property.
private void button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
if (button == null)
return; //Some error/exception
Panel parentPanel = button.Parent as Panel;
if (parentPanel == null)
{
//Parent container is not panel
}
//Otherwise get the panel properties.
}
I'll assume all the "Add" buttons are subscribed to this same event.
The value of sender will be the particular "Add" button that was just clicked. Then you can cast the button's Parent to a Panel:
var button = (Button)sender;
var parentPanel = (Panel)button.Parent;
These two lines will be sufficient as long as
You don't accidentally attach some other control other than a button to this event
All the "Add" buttons are contained within a Panel.

How to get the context of the button rightclicked

I have encountered some problems in the bookmark section for my wpf web-browser. I want to be able to delete already existing buttons but I can't seem to figure out how to detect the content of the button I right click on. (To get my ContextMenu to show).
My visual progress so far: http://puu.sh/6Dxat.png
Adding a context menu to the buttons:
public void button_MouseRightButtonDown(object sender, MouseButtonEventArgs e)//add a context menu to buttons
{
Button button = sender as Button;
menu = new ContextMenu();
menu.Items.Add(new MenuItem() { Header = "Delete" });
button.ContextMenu = menu;
menu.Closed += button_DeleteButtonClicked;//find the right event
}
(I know that the event is wrong, but that is not important right now.)
And the event:
private void button_DeleteButtonClicked(object sender, RoutedEventArgs e)//delete bookmark
{
//This is where I need help. I want the content (which is the URL) of the button
//right clicked onto, for example, show up in a messagebox. How to do?
}
Since you have hooked Close event of context menu here, so sender will be ContextMenu here and you can get button by using PlacementTarget property of ContextMenu.
private void button_DeleteButtonClicked(object sender, RoutedEventArgs e)
{
Button button = ((ContextMenu)sender).PlacementTarget as Button;
}

How to get the item right clicked on from ContextMenuStrip?

I have a PictureBox.
If I right click the PictureBox, my ContextMenuStrip (right click menu) appears.
In that ContextMenuStrip is a ToolStripMenuItem (one of the options in the right click menu).
There is an event on the ToolStripMenuItem that handles what happens if that option is clicked.
We're starting from ToolStripMenuItem's "Clicked" function. I need to somehow get back to the PictureBox programmatically. From there, I can modify the PictureBox.
ToolStripMenuItem -> ContextMenuStrip -> PictureBox
How would I go about this?
If the click event handler for your menu item is named OnToolStripMenuItemClick, the following might be an approach to your problem:
private void OnToolStripMenuItemClick(object sender, EventArgs e)
{
var menuItem = sender as ToolStripMenuItem;
var contextMenu = menuItem.Parent as ContextMenuStrip;
var pictureBox = contextMenu.SourceControl;
}
Of course, don't forget to check for null when accessing properties after conversion with as.
I'm not sure that I really understood your problem, but I guess you want to let users can return to the picturebox when they want to cancel current operation by clicking the right button. In this case, you should not implement your work in click event, because right and left button both can trigger the click event, instead, you should process your work in the event "MouseUp", like this:
private void menuItemBack_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
MessageBox.Show("back item is clicked");
}
else
{
MessageBox.Show("I will come back.");
//do your return things here.
}
}
I've just come across this same problem in C#, and the path to the value seems to be something like:
sender.Owner.SourceControl;
However, since sender, Owner and so on are generic classes, I had to cast everything as follows:
PictureBox pb = (PictureBox) ((ContextMenuStrip)((ToolStripMenuItem)sender).Owner).SourceControl;
Ugly, but it works.

Event Bubbling in WPF Application

I'm new to WPF. In my WPF app, I have Windows which contain a user defined child control and that user defined child control again contains another user defined child control. Now from the inner most child control, on a button click, I want to fire events on all three controls (i.e. First Grand Child Control, Second Child Control, Third Main Control, and Window).
I know this can be achieved through delegates and Event Bubbling. Can you please tell me how?
Most important piece pf code for that:
Add the event handlers on the static UIElement.MouseLeftButtonUpEvent:
middleInnerControl.AddHandler(UIElement.MouseLeftButtonUpEvent , new RoutedEventHandler(handleInner)); //adds the handler for a click event on the most out
mostOuterControl.AddHandler(UIElement.MouseLeftButtonUpEvent , new RoutedEventHandler(handleMostOuter)); //adds the handler for a click event on the most out
The EventHandlers:
private void handleInner(object asd, RoutedEventArgs e)
{
InnerControl c = e.OriginalSource as InnerControl;
if (c != null)
{
//do whatever
}
e.Handled = false; // do not set handle to true --> bubbles further
}
private void handleMostOuter(object asd, RoutedEventArgs e)
{
InnerControl c = e.OriginalSource as InnerControl;
if (c != null)
{
//do whatever
}
e.Handled = true; // set handled = true, it wont bubble further
}
Have a look at this http://msdn.microsoft.com/en-us/library/ms742806.aspx
This page explains all about routed events, including how to implement and consume them.

Categories