This question already has answers here:
Handling a Click for all controls on a Form
(2 answers)
Closed 6 years ago.
I am designing a small application in which I open a new form with some controls. I want to close this form if idle for some time. Let say the form is having many buttons, scroll bars, picture box....if none of them is clicked (within 10 seconds) the form should close.
I have used a timer of 10 seconds , i want to reset it if any of the control is pressed. I can do it individually but would become very cumbersome doing it for all the controls. Can i do it by some simpler way....I read on net:
foreach (Control cc in Controls)
but didn't knew how to use it. Please help.
This should get you started
private void Form1_Load(object sender, EventArgs e)
{
foreach(Control control in this.Controls)
{
control.Click += Oncontrol_Click;
}
}
private void Oncontrol_Click(object sender, EventArgs e)
{
Control control = sender as Control;
MessageBox.Show($"{control.Text} is clicked");
}
You can bind the click event to all the controls inside the foreach loop.
foreach (Control c in Controls)
{
c.Click += (o, args) => ResetTimer();
}
Now each time a user clicks a control, ResetTimer() gets fired.
You need to do this to add the click event to all of the controls on a form:
private void Form1_Load(object sender, EventArgs e)
{
AttachHandler(this, (s, e2) => ResetTimer());
}
private void AttachHandler(Control control, EventHandler handler)
{
control.Click += handler;
foreach (Control c in control.Controls)
{
AttachHandler(c, handler);
}
}
It needs to recursively go down all controls that can contain other controls.
Related
Is there any WindowsFormApp listener method that automatically monitors events from child elements?
Clicking a button, opening a list, etc... without each one having its own method?
I'm trying to automate the event process bound to WindowsFormApp components. Example:
There are 10 buttons and I want a single method to monitor the actions of those 10 buttons or any other contained element. I already tried the manual method said at Set the handler. I want to know if there is an automated way, that is, some method of WindowsFormApp that is able to identify these events.
I await reply..
Thank you!
All very well!
I applied the following snippet to define the Click event of any element that has this action.
foreach (Control grandChild in this.Controls) grandChild.Click += new System.EventHandler(this.Handle_events);
private void Handle_events(object sender, EventArgs e)
{
Console.WriteLine(sender);
}
You may add Event Handlers dynamically to ensure that they are the same for all children.
Panel p = new();
Button a = new();
Button b = new();
p.Controls.Add(a);
p.Controls.Add(b);
foreach (Button button in p.Controls) button.Click += Button_Click;
void Button_Click(object sender, EventArgs e)
{
((Button)sender).Text = "I was clicked";
}
I wanted to focus to a TextBox when I leave an other TextBox.
Let's say I have 3 textboxes. The focus is in the first one, and when I click into the second one, I want to put the focus into the last one instead.
I subscribed to the first textbox's Leave event and tried to focus to the third textbox like: third.Focus(). It gains focus for a moment but then the second one got it eventually (the one I clicked).
Strangely if I replace the second TextBox to a MaskedTextBox (or to any other control), the focus remains on the third one.
Pressing Tab does work though.
These are plain textboxes right from the toolbox.
What is the reason, how can I solve this?
Try to handle Enter event of the textBox2. (In properties window double click on Enter event)
//From Form1.Designer.cs
this.textBox2.Enter += new System.EventHandler(this.textBox2_Enter);
private void textBox2_Enter(object sender, EventArgs e)
{
textBox3.Focus();
}
EDIT:
This code looks very strange, but it works for me. According to this post HERE I use ActiveControl property instead of Focus() method. But behavior of TextBox is very strange because it try to be focused multiple times.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
foreach (Control control in Controls)
{
control.LostFocus += (s, e) => Console.WriteLine(control.Name + " LostFocus");
control.GotFocus += (s, e) =>
{
Console.WriteLine(control.Name + " GotFocus");
if (!requestedFocusToTextBox2) return;
ActiveControl = textBox2; //textBox2.Focus() doesn't work
requestedFocusToTextBox2 = false;
};
}
}
private bool requestedFocusToTextBox2;
private void textBox1_Leave(object sender, EventArgs e)
{
ActiveControl = textBox2;
requestedFocusToTextBox2 = true;
}
}
This question already has answers here:
How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?
(28 answers)
Closed 2 years ago.
What I am trying to do is to change background color of the button once it's active. So far I achieved it by this way:
private void button3_Click(object sender, EventArgs e) // METEO BUTTON
{
DefaultButtons();
button3.BackColor = Color.LimeGreen;
// REST OF THE CODE HOES HERE
}
While DefaultButtons function is like this:
public void DefaultButtons()
{
List<Button> buttonsToDefualt = new List<Button>()
{
// MAIN MENU
button1,
button2,
[...]
buttonX
};
foreach (var item in buttonsToDefualt)
{
item.BackColor = Color.Green;
}
}
Now swapping buttons works like this: Change entire list to default color, then activated button change color to LimeGreen. It would be fine but:
1) I have to launch DefaultButtons(); for EACH button Click
2) I have to manually add all buttons to list, and now I have more than 120 buttons (Yeah, building custom interface...), and keep adding that by hand is tiring.
I tried this:
void DefaultButtonsNew()
{
foreach (Button b in this.Controls)
{
if (b != null)
{
b.BackColor = Color.Green;
}
}
}
But I've got an Exception: System.InvalidCastException: 'Can't throw object 'System.Windows.Forms.SplitContainer' on type 'System.Windows.Forms.Button'.'
If you're looking for a way to reset all buttons on the form, and some buttons are inside other containers, then we need to recursively loop through each control's Controls collection to find all the buttons.
One easy way to do that is to write a method that takes in a container (like the form), iterates through its Controls collection, changes the BackColor of any Button controls, and calls itself for the other control types:
private void ResetButtons(Control container)
{
// Loop through each control in this container
foreach (Control control in container.Controls)
{
var button = control as Button;
// If the control is a button, change it's backcolor
if (button != null) button.BackColor = Color.Green;
// Otherwise check it's controls collection (recursive call)
else ResetButtons(control);
}
}
Next, it sounds like you're looking for a way to avoid writing out a call to this method, and to change the BackColor of the current button, in every button click event.
One easy way around this is to simply add this method, and the BackColor change, to every button click in code. We can write a method to do this using a similar pattern - loop through every control in every container, and if it's a button, add a method to it's click event:
private void HookupButtonClickEvent(Control container)
{
// Loop through each control in this container
foreach (Control control in container.Controls)
{
var button = control as Button;
// If the control is a button, add a method to it's click event
if (button != null)
{
button.Click += (s, e) =>
{
ResetButtons(container);
button.BackColor = Color.LimeGreen; // Change this button's color
};
}
// Otherwise check it's controls collection (recursive call)
else HookupButtonClickEvent(control);
}
}
Now, all we have to do is call the ResetButtons and HookupButtonClickEvent in our form's constructor, and every button will start with the same backcolor and will have our reset method call in it's click event:
public Form1()
{
InitializeComponent();
HookupButtonClickEvent(this);
ResetButtons(this);
}
Note that this does not prevent you from adding additional click events to the buttons. It merely provides a way to hook up the common functionality to all buttons without writing a bunch of duplicated code.
You can still double-click the controls on your form to add other Click event handlers:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Button one clicked - doing something unique here");
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Button two clicked - doing something else here");
}
The iterator on Controls collection returns all the controls and trying to cast it to Button should an do fail.
Change your method like this:
void DefaultButtonsNew()
{
foreach (Control b in this.Controls)
{
if (b is Button)
{
b.BackColor = Color.Green;
}
}
}
I have a form with many labels and text boxes. I'd like to have the title highlighted red if any of the fields are modified. Is there an easy way to do this or do you need to add the event callback to each form object individually? Thanks!
Off the top of my head you could do something like this in the form load event to add the events...
foreach (var control in this.Controls)
{
if (control is Label)
{
((Label)control).TextChanged += Controls_TextChanged;
}
else if (control is TextBox)
{
((TextBox)control).TextChanged += Controls_TextChanged;
}
}
When you're looking at the events associated with each control, you notice that you can 'drop down' a list of all events coded in the form. If you double click on a 'Text Changed' event, for example, it will be controlname_textchanged(...). However, if you have a generic handler for all, then you could call it textchangedevent(...). The generic event handler will need to have the sender and event object associated with that event in the parameters.
If you're doing this in a user control and have to update the main form, then you will bubble this up through a public event eventobject youreventname, and bind that event on the main form.
Something like this should work:
foreach (System.Windows.Forms.Control cont in this.Controls)
cont.Validating += new System.Windows.Forms.ValidationEventHandler(this.Control_Validating_Method)
Then you could test for the control type in the event code and compare the value with the original value.
Yes you can easily add controls to the same event. This example puts the 'Labels' and 'Textboxes' in the same event.
private void Form1_Load(object sender, EventArgs e)
{
foreach (Control x in this.Controls)
{
if(x is Label)
((Label)x).MouseHover+=new EventHandler(AllLabels_HoverEvent);
else if(x is TextBox)
((TextBox)x).MouseHover+=new EventHandler(AllTextboxes_HoverEvent);
}
}
void AllLabels_HoverEvent(object sender, EventArgs e)
{
Label label = (Label)sender;
// label.dowhateveryouwant...
}
void AllTextboxes_HoverEvent(object sender, EventArgs e)
{
Textbox textbox = (Textbox)sender;
// textbox.dowhateveryouwant...
}
If you need any more clarification please comment below and I will add on to my answer or modify it to suite any particular needs you have. Be careful though if you have controls nested in other containers they won't be in this.Controls.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How can I invoke an event handler from a function?
I need to do something I was pretty sure should be simple, I have Form with controls and every control have event handler that sets label with correct formating etc.
What I need is to call every handlers collection for every control on specific type.
I browsed all stackoverflow and never saw result.
It is simple application so please stop comments like: "you need additional function called from event handler".
This is what I tried
foreach (Control ctrl in Controls)
{
if (ctrl is TrackBar)
{
TrackBar tb = ctrl as TrackBar;
Invoke(tb.Scroll, tb, new EventArgs());
}
}
But I see very strange error
The event 'System.Windows.Forms.TrackBar.Scroll' can only appear on the left hand side of += or -=
Any solution?
You can't raise event outside class in which event is declared (only adding and removing handlers is available). Instead of trying to raise event, which will call event handler, simply extract handler logic to separate method, and call that method:
foreach (TrackBar tb in Controls.OfType<TrackBar>())
{
DoSomething(tb.Value);
}
And handler:
void trackBar_Scroll(object sender, EventArgs e)
{
DoSomething(((TrackBar)sender).Value);
}
Error appears because tb.Scroll is event not delegate.
You could try making a delegate with the same Signature as the Event, create a common eventhandler for your controls and then you can either invoke it or respond to the event as normal.
i.e.
Something like this:
public partial class Form1 : Form
{
public delegate void trackbarscroll( object sender, EventArgs e);
trackbarscroll tbs;
public Form1()
{
InitializeComponent();
trackBar1.Scroll += new EventHandler(trackBar_Scroll);
trackBar2.Scroll += new EventHandler(trackBar_Scroll);
tbs = trackBar_Scroll;
}
void trackBar_Scroll(object sender, EventArgs e)
{
TrackBar tb = (TrackBar)sender;
}
private void button1_Click(object sender, EventArgs e)
{
foreach (Control ctrl in Controls)
{
if (ctrl is TrackBar)
{
TrackBar tb = ctrl as TrackBar;
Invoke(tbs,tb, new EventArgs());
}
}
}
}