I have a Winforms c# form with some comboBoxes , cancel and save buttons that work fine.
I now need to capture when the user has finished entering text into a comboBox.
I add an empty ( for now) lostFocus (or Leave) event to the combbox , which triggers fine. However if the cause of that event was a cancel or save button press , the corresponding event is no longer triggered. These buttons still work fine if pressed at other times.
Should these two event be firing in sequence or is there some better way to capture completed text entry?
The Leave and/or LoseFocus events do not get triggered because you do not leave the combobox and because it doesn't lose focus when you press Enter or Escape.
Therefore the best way is to add the function you are triggering in the LoseFocus event, also to the Button click events of the Cancel- and the Accept-Buttons.
Adding a call to the leave event itself: comboBox1.Leave(null, null); would be the simplest way.
To make sure that the function is called only once, I check who has focus in the ButtonClick events:
private void acceptButton_Click(object sender, EventArgs e)
{
if (comboBox1.ContainsFocus) comboBox1_Leave(acceptButton, null);
// do accept stuff here..
}
private void cancelButton_Click(object sender, EventArgs e)
{
if (comboBox1.ContainsFocus) comboBox1_Leave(cancelButton, null);
// do cancel stuff here..
}
private void comboBox1_Leave(object sender, EventArgs e)
{
// do leave stuff here..
Console.WriteLine(sender);
}
I also pass in the Button so you could check the sender to see how the Leave was triggered..
I'm answering my own question here as I feel it might be useful to other newbies.
The breakpoint I had set in my empty lostFocus event was stopping button click event from occurring. When I removed the breakpoint the problem went away.
However when I added code to my lostFocus event, a form redraw was sometimes moving the buttons and preventing their events from firing. To solve this problem I adapted TaWs very useful answer and fired the button event from within the lostFocus event.
private void comboBox1_LostFocus(object sender, EventArgs e)
{
bool saving = btnSave.ContainsFocus;
// form redraw stuff here..
if (saving)
btnSave_Click(btnSave, null);
}
Related
Something strange is happening in my WinForms app (and with strange things it's normally my fault).
I've got a FormClosing event that will check whether any changes has been made on the form that has not been saved.
If the user confirm to save the changes, I will call the Save button's click event. However, even if I remove all the logic in the OnClick event, the form stays open, and I have to close it again before it closes.
If I skip the line buttonSave.PerformClick(); then the form closes properly.
Why will entering the click event, cancel the close? Any work around?
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
//Check if there changes were made on the form
//Prompt user to save
if (confirmSave)
buttonSave.PerformClick();
}
private void buttonSave_Click(object sender, EventArgs e)
{
//Everything in here commented out.
}
Just call the event instead of PerformClick.
PerformClick probably executes more code that makes the form stop closing. Like showing that the button is clicked, the sound etc.
So change PerformClick to buttonSave_Click. So it will just do the save function, without doing anything with the button itself.
I have a WinForm which contains a multitude of controls interdependent on each other for their visibility and content.
I have a pair of radio buttons, controlling a combobox's (ComboBoxA) enable/disable flag and content. The selection on this combobox controls the visibility of a checkbox. The checking of this checkbox controls another combobox's (ComboBoxB) visibility and content. Business requirements are quite complicated around these controls. As a result, I require the ability to fire of the events programmatically and through user action, doing different things in each case.
In the checkbox's case, I check it programmatically while loading data (if needed), which fires the CheckedChanged event which in turn does additional action controlling ComboBoxB. The code for this is pretty vanilla, nothing special, but my question is more theoretical than practical. Please keep reading.
Due to this requirement, I need a way to distinguish between programmatic checking and user action. I tried using the Click event and CheckedChanged event, setting a flag in the click event, signifying user action. Unfortunately, the CheckedChanged event fires before the Click event, dead-ending this trick.
Now, I tried using the MouseDown event to capture user action. But funnily enough, once the event fires, checkbox remains unchecked and the CheckedChanged event doesnt fire.
Now, I have managed to use a flag in the code to determine programmatic checking and use that to distinguish between the two, but I was curious as to why the MouseDown event didnt allow the checkbox to be checked. Any ideas? I searched online but either I didnt do a thorough job of it, or google is not returning the right results for me. I apologize if anybody is actually able to find a google result for this problem.
It's something else in your code, not the MouseDown event that's preventing the CheckChanged to be fired.
Here is how I know this:
I've added a checkbox and a button to an empty form, and added event handlers to Click on the button, and on the checkbox CheckedChanged, KeyDown and MouseDown events. I've also added to the form a string variable called LastEventRaised, and in the CheckedChanged I've simply shown a MessageBox:
string LastEventRaised = string.Empty;
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
MessageBox.Show("Checked changed " + LastEventRaised);
LastEventRaised = string.Empty;
}
private void checkBox1_KeyDown(object sender, KeyEventArgs e)
{
LastEventRaised = "KeyDown";
}
private void checkBox1_MouseDown(object sender, MouseEventArgs e)
{
LastEventRaised = "MouseDown";
}
private void button1_Click(object sender, EventArgs e)
{
LastEventRaised = "programmatically";
checkBox1.Checked = !checkBox1.Checked;
}
Each time the message box popped up I've got the correct message.
I am having trouble getting my application to work correctly. I am trying to select a row in a datagridview with the mouse. I need to save the index of this row to allow me to navigate around the selected row.
I have been looking at DataGridView.CellMouseClick Event (Link) But I am unable to ensure that the event handler is associated with the CellMouseClick event.
My code for this so far is simple, Im just trying to see if its detecting mouse clicks:
public event DataGridViewCellMouseEventHandler CellMouseClick;
private void DataGridView1_CellMouseClick(Object sender, DataGridViewCellMouseEventArgs e)
{
MessageBox.Show("Mouse clicked in the datagridview!");
}
Can anyone point out where I may be going wrong. Any help would be great!
You need to "wire up" the event.
If your DataGridView is called DataGridView1 then you need the following line of code in either the constructor for your form, the designer (if you add the event handler via the designer) or in the Load event:
DataGridView1.CellMouseClick += DataGridView1_CellMouseClick;
This attaches the event handler in your code to the event.
Your current sample looks like this:
public event DataGridViewCellMouseEventHandler CellMouseClick;
private void DataGridView1_CellMouseClick(Object sender, DataGridViewCellMouseEventArgs e)
{
MessageBox.Show("Mouse clicked in the datagridview!");
}
There is no need to redeclare the event (public event DataGridViewCellMouseEventHandler CellMouseClick;) unless you are building your own user control that will host a DataGridView and you effectively want to "wrap" or "rebroadcast" that event.
here's my problem .. i'm doing a calculator in C# and i don't want to click every single button to make a operation, i wanna handle it with my num pad .. like
if i press "1" , show me in the textbox "1".
i changed
private void cmd1_Click(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '1')
{
txtShow.Text='1';
}
}
and i'm having this error :
No overload for 'cmd1_Click' matches delegate "System.EventHandler"
this.cmd1.Click += new System.EventHandler(this.cmd1_Click);
what the hack is wrong with this?
Cheers.
change
this.cmd1.Click += new System.EventHandler(this.cmd1_Click);
to
this.cmd1.KeyPress += new System.EventHandler(this.cmd1_Click);
You'll probably want to rename cmd1_Click too.
And as mentioned in the answer above, this would be better on the Form itself, rather than each button.
You are trying to attach an event handler that corresponds to a KeyPress event to a Click event.
There is something wrong here (bad copy/paste?):
private void cmd1_Click(object sender, KeyPressEventArgs e)
It's named as an auto-generated event handler for the Click event on cmd1, but its definition is the definition for a KeyPress event handler.
Which event do you want to handle? KeyPress or Click or both?
Click is a mouse event, you need to attach to a keyboard event if you want to receive keyboard event args, you'd have to put all your calculator buttons in a common pannel and handle both the button click "and" the text being sent to the panel, that way you could react to both keypresses anywhere and to click for the same result.
An easy way to handling events for all the buttons without doing it one by one is to have a single button click handler and check the text property of the control to know how to act (cast the sender to a button and check the text, do a switch on that)
Not tested:
switch(((button)sender).Text)
{
case "1":
// react to user having pressed 1 etc etc
}
I am working on a C# WinForm application.
I want to trigger some processing once the form has been "shown" and the layout of the form is complete.
I am using the "_Shown" event, but this seems to trigger before the layout of the form has completed. Is there event I can use that fires once the layout is complete?
Put Application.DoEvents() at the start of the form's Shown event handler. This will force all the controls to be rendered.
I don't see an event after Shown you can use for this purpose. Could you not use a timer to delay your processing in the Shown event?
An old trick in VB6 used to be to use the Paint event:
bool firstShown = false;
void form_Paint(Object sender, EventArgs e) {
if ( !firstShown ) {
YourMethodThatNeedsToRunOnShown();
firstShown = true;
}
//the rest of your paint method (if any)
}
It is a little hacky, but it does work
This works for me and is much less "hacky" than other suggestions:
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if(someControl == null)
return; // be careful of OnLayout being called multiple times
// otherwise, do some stuff here, set control sizes, etc.
}
AS far as I can remember the event order is something like
Form.Load
Form.Layout
Form.VisibleChanged
Form.GotFocus
Form.Activated
Form.Shown
So if something is still happening after Form.Show it's because of the way you coded it.
Are you maybe creating the form dynamically?
The best solution is the Shown() event: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.shown.aspx
"The Shown event is only raised the first time a form is displayed; subsequently minimizing, maximizing, restoring, hiding, showing, or invalidating and repainting will not raise this event."
Try using Form.GotFocus (inherited from control)..
something like this.
private void Form1_Load(object sender, EventArgs e)
{
this.GotFocus += new EventHandler(Form1_gotFocus);
this.Focus();
}
private void Form1_gotFocus(object sender, EventArgs e)
{
// You will need to Switch focus from form at the end of this function,
//to make sure it doesnt keep Firing.
}
According To msdn , the following happens:
When you change the focus by using the keyboard (TAB, SHIFT+TAB, and so on), by calling the Select or SelectNextControl methods, or by setting the ContainerControl..::.ActiveControl property to the current form, focus events occur in the following order:
Enter
GotFocus
Leave
Validating
Validated
LostFocus