How to wire up an EventHandler on a Winforms Application? - c#

I have an application and I want to start a countdown timer.
I created an EventHandler under the partial class:
event EventHandler startTimer;
And I wrote a function:
public void startTimerEvent(object sender, EventArgs e)
{
this.Invoke((MethodInvoker)delegate
{
timer.Start();
});
}
How can I register this to the EventHandler and where do I wire it up in my form?

To tie the event to the handler:
startTimer += startTimerEvent;
But I'm not really sure there isn't a better way to go about solving your general problem. If you could describe further what you're after, perhaps we could suggest a better way.

So you need to choose an event that will trigger your handler. Let’s say you have a button, and you want to handle its click event. You could write:
myButton.Click += new EventHandler(StartWhatEver);
Then you would have your StartWhatEver that does what you want.
private void StartWhatEver(object sender, EventArgs e)
{
// Do stuff...
}
Note: If you are working in VS2010, you can type myButton.Click += (with space) then double tap the 'Tab' key and this will create your handler for you automatically including the triggered method.
Hope this helps.

Related

user control and raising events from controls placed in user control

So I would like to know what is wrong with the following code, especially from a theoretical point of view.
I have a user control in which I've added a text box.
When I click in the text box I would like the Mouse clicked event raised in the user control.
To my mind, the solution should be:
Create an event handler for the mouse click event in the text box.
in this event handler, raise the mouse click event for the user control.
so this is what i have:
private void txtLog_MouseClick(object sender, MouseEventArgs e)
{
this.OnMouseClick(e);
}
i have tried it and it doesn't work, why is this?
P.S. I would really like to know why this is wrong! A correct solution is great, but I'm really trying to understand where I'm going wrong here. Thank :-)
Well, you could just click on your textbox in design mode and in the property window in events tab add the click event. or if you want to do it in runtime you can do it like this:
textbox.Click += Txt_Click;
private static void Txt_Click(object sender, EventArgs e)
{
// do your thing
}
or even shorter:
textbox.Click += (s,e) =>
{
//do your thing
};
you should do these three steps
declare an MouseClick delegation method for textbox
assign method to textbox
add this delegation to the this (form) OnMouseClick event [on user control constructor]
Step1:
private void textBox1_MouseClick(object sender, MouseEventArgs e)
{
}
Step2:
this.textBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.textBox1_MouseClick);
Step3:
public myUserControl()
{
InitializeComponent();
this.MouseClick += new MouseEventHandler(textBox1_MouseClick);
}

Handle press and release of button

I want a button to function like this:
if button is down(mouse button is hold down)
{
bool trySmthing = true;
}
if button is up
{
bool trySmthing = false;
}
I tried some stuff with KeyUp and KeyDown events but they don't give the right result.
Apparently the focus must be in your application; a tutorial on handling the mouse events via the .NET framework in C# can be found here. The MouseDown event, as documented here and the MouseUp event, as documented here, are of particular interest..
This should help: Micosoft Library for C# Mouse-events
void MouseUpHandler(Object sender, RoutedEventArgs args)
{
// This method is called whenever the PreviewMouseUp event fires.
}
void MouseDownHandler(Object sender, RoutedEventArgs args)
{
// This method is called whenever the PreviewMouseDown event fires.
}

Prevent multiple firing of keydown events C#

I want to allow the user to send his message when he press enter in the textbox.
I went to search and im using the sample codes below.
Now the problem is when i press enter, the event is triggered more than once like about 4-5 times.
Someone else suggested to use keyup. I have tried keyup, keydown and keypress. All have the same problem.
How do i prevent it from firing the event more than once?
private void tbxAnswer_TextChanged(object sender, EventArgs e)
{
tbxAnswer.KeyUp += new KeyEventHandler(tbxAnswer_KeyUp);
}
private void tbxAnswer_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyValue == (char)13)
{
MessageBox.Show("Hello");
}
}
Thank you!
You are adding the KeyUp event handler multiple times (inside the TextChanged handler); therefore, when Enter is pressed, the handler executes multiple times.
What you want to do here is add the KeyUp handler just once, inside your form's constructor, just after the InitializeComponent() call:
public MyForm()
{
// other code possibly here
InitializeComponent();
// and now add the event handler:
tbxAnswer.KeyUp += new KeyEventHandler(tbxAnswer_KeyUp);
}
private void tbxAnswer_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyValue == (char)13)
{
MessageBox.Show("Hello");
}
}
This is because every time you change the text, the tbxAnswer_TextChanged is called/ fired you assign an action to the keyup event; if the text is changed 4 times then you assigned the keyup event 4 times and it increases every time you change the text.
try this out:
tbxAnswer.KeyUp += new KeyEventHandler(tbxAnswer_KeyUp);
private void tbxAnswer_TextChanged(object sender, EventArgs e)
{
}
private void tbxAnswer_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyValue == (char)13)
{
MessageBox.Show("Hello");
}
}
Change your code to this
tbxAnswer.KeyUp -= tbxAnswer_KeyUp;
tbxAnswer.KeyUp += new KeyEventHandler(tbxAnswer_KeyUp);
In your code snippet, whenever the text of the TextBox changes, another eventhandler is added to the KeyUp handler. You should only add event handlers once (for instance, just after creating the textbox).
Sara and Jon have already provided the correct answer to your specific question. But if you want to go further and get a better understanding of how and when to use any particular key handling event take a look at my article Exploring Secrets of .NET Keystroke Handling. I explain and diagram when and where each event is useful, plus provide a KeystrokeSandbox application that lets you actually watch what happens!

Event fires more and more times

I have a silverlight mvvm application that loads main view with 2 user controls loaded into 2 ContentControls, one with listbox showing items and other with edit button. When i click edit button, 2 new user controls load into the ContentControls, one showing data to edit (EditData) and other having Save and Cancel button (EditAction).
When i click save button, it raises an event that is defined in seperate GlobalEvents.cs class like:
public event EventHandler OnSaveButtonClicked;
public void RaiseSaveButtonClicked()
{
this.OnSaveButtonClicked(this, EventArgs.Empty);
}
and i subscribe to it in the other user control EditData, because i need to transfer that edited data via custom EventArgs, so i have put in the constructor of it's ViewModel:
this.globalEvents.OnSaveButtonClicked += (s, e) => SaveData();
and in the Save data:
public void SaveData()
{
globalEvents.RaiseSaveData(EditedGuy);
}
which raises another event that loads previous user controls into their ControlContent and shows edited data in list box. Thats all fine, but whenever i click on edit and then save again, it raises the event twice, and again 3 times, then 4 and so on. How can i make it to be raised only ONE time? I thought it could be because every time i click edit, a new instance of the user control is loaded and i dont know, maybe the subscription to the event stays, so i have tried to paste
this.globalEvents.OnSaveButtonClicked -= (s, e) => SaveData();
to the Dispose() method but without success. How can i make this work?
You can't use lambdas when you want to unregister from events.
this.globalEvents.OnSaveButtonClicked += (s, e) => SaveData();
This will create one instance - let's call it instance A - of type EventHandler and add it as a handler.
this.globalEvents.OnSaveButtonClicked -= (s, e) => SaveData();
This will not remove instance A from the event but create a new instance - instance B - and tries to remove it from the event.
To fix this problem, either create a little method or save that anonymous method in a field:
class ViewModel
{
private EventHandler _saveButtonClickedHandler;
// ...
public ViewModel()
{
_saveButtonClickedHandler = (s, e) => SaveData();
this.globalEvents.OnSaveButtonClicked += _saveButtonClickedHandler;
// ...
}
public void Dispose()
{
this.globalEvents.OnSaveButtonClicked -= _saveButtonClickedHandler;
// ...
}
// ...
}
this.globalEvents.OnSaveButtonClicked += (s, e) => SaveData();
This line is being called multiple times so you are adding a new event handler every time.
You need to either move that line to somewhere where it's only called once or change the event handler to:
this.globalEvents.OnSaveButtonClicked += SaveData;
public void SaveData(object sender, EventArgs e)
{
globalEvents.RaiseSaveData(EditedGuy);
this.globalEvents.OnSaveButtonClicked -= SaveData();
}
So you remove the event handler after dealing with it. This assumes that the handler will be added back next time you go into edit mode.
You could define a private eventhandler delegate variable in your class and assign it in your constructor:
private SaveButtonClickedHandler _handler;
Assign the handler in your constructor:
_handler = (s,e) => SaveData();
this.globalEvents.OnSaveButtonClicked += _handler;
Dispose:
this.globalEvents.OnSaveButtonClicked -= _handler;
"SaveButtonClickedHandler" is pseudo-code/placeholder for whatever the name of the delegate should be.
Hasanain
You'll have to put in a proper event handler method that calls SaveData() and register/unregister that. Otherwise you try to unregister another "new" anonymous method instead of the original one you've registered, which you, because it is anonymous, cannot actually access anymore.
public void SaveButtonClicked(object sender, EventArgs e)
{
SaveData();
}
this.globalEvents.OnSaveButtonClicked += SaveButtonClicked;
this.globalEvents.OnSaveButtonClicked -= SaveButtonClicked;

Why is there an infinite loop on my LostFocus Event

I'm a beginner with C# and I'm developing a basic application.
I want to check if the value of a textbox is a number with the following code :
private void check_value(object sender)
{
TextBox tb = (TextBox)sender ;
if (!Utility.isNumeric(tb.Text)){
MessageBox.Show(tb.Text.Length.ToString());
tb.Focus();
}
}
private void Amount_1_LostFocus(object sender, RoutedEventArgs e)
{
check_value(sender);
}
When I enter a letter in the textbox there is an infinite loop and it seems that the tb.Focus() actually cause the LostFocus event to be call recursively.
I don't understand why the call to the Focus method of an object triggers the LostFocus event of the same object.
Opening the modal MessageBox is responsible for loosing the focus. Try hook to Validating event.
As i said before in the link provided by Xaqron it's said that it's forbidden to use the Focus method in the LostFocus event.
And as I'm developing a WPF application there is no Validating event and CausesValidation property, so the others ways to validate the content is to use the TextChanged event or use binding validation.
Thank you for your answers.
Of course, in a perfectly valid program, you should not change Focus in the LostFocus event. This also applies to the Enter, GotFocus, Leave, Validating and Validated events, which Ms makes clear in the documentation https://learn.microsoft.com/pl-pl/dotnet/api/system.windows.forms.control.lostfocus.
However, in very unusual cases, you can use the timer to trigger changes to the Focus, bypassing this problem.
private TextBox tb = null;
private System.Windows.Forms.Timer MyTimer;
private void initialize()
{
MyTimer.Tick += new System.EventHandler(MyTimer_Tick);
MyTimer.Enable = false;
MyTimer.Interval = 100;
}
private void check_value(object sender)
{
tb = (TextBox)sender ;
if (!Utility.isNumeric(tb.Text)){
MessageBox.Show(tb.Text.Length.ToString());
MyTimer.Enable = true;
}
}
private void Amount_1_LostFocus(object sender, RoutedEventArgs e)
{
check_value(sender);
}
private void MyTimer_Tick(object sender, EventArgs e)
{
MyTimer.Enabled = false;
if (tb!=null) tb.Focus();
}

Categories

Resources