How to run two different events with separated PostBacks on Button Click - c#

I have Button with code:
protected void Button1_Click(object sender, EventArgs e) {
Label1.Text = "Searching for services";
UpdatePanel1.Update();
}
but in addition I need to show something when I will find my services so I add another event:
Button1.Click += (s, k) => {
discovery.FindAlreadyRegisteredServices();
discovery.discoveryClient.FindCompleted += FoundEvent;
auto[1].WaitOne();
UpdatePanel1.Update();
};
which is slow (and controlled by AutoResetEvent)
protected void FoundEvent(object sender, FindCompletedEventArgs e) {
Label1.Text = "Found " + ((discovery.endpoints.Count > 0) ? discovery.endpoints[0].Address.ToString() : "nothing");
auto[1].Set();
}
The problem is that my Button1.Click += (s, k) => just makes no sense at all because it executes after Button1_Click and there is no PostBack until all the bonded events will be finished?
I know that I can use everything I want right on client by using UpdateProgress and javascript but what I want here is client to sent 2 events and wait for 2 answers, make 2 PostBacks. Is it possible?

protected void Button1_Click(object sender, EventArgs e) {
Label1.Text = "Searching for services";
//change postback hooks
Button1.Click -= Button1_Click;
Button1.Click += AnotherEventPB;
ScriptManager.RegisterStarupScript(this, GetType(), postback, "__doPostBack();", true);
UpdatePanel1.Update();
}
protected void AnotherEventPB(object sender, EventArgs e)
{
//reset postback hooks
Button1.Click -= AnotherEventPB;
Button1.Click += Button1_Click;
discovery.FindAlreadyRegisteredServices();
discovery.discoveryClient.FindCompleted += FoundEvent;
auto[1].WaitOne();
UpdatePanel1.Update();
}

I know that I can use everything I want right on client by using UpdateProgress and javascript but what I want here is client to sent 2 events and wait for 2 answers, make 2 PostBacks.
Why? It seems like an arbitrary constraint that's making an otherwise trivial task unnecessarily complicated.

Related

button click event is not change

i need some help what is wrong in this code
protected void Page_Load(object sender, EventArgs e)
{ }
protected void Button1_Click(object sender, EventArgs e)
{
Button1.ID = "Button4";
Button2.ID = "Button1";
Button1.Click -= Button1_Click;
Button1.Click +=new EventHandler( Button2_Click);
//Button2.ID = "Button1";
}
protected void Button2_Click(object sender, EventArgs e)
{
Response.Write("success");
}
When i click on button1, it calls button1_click and when i click on button2, it also calls button1_click instead of button2_click.
I believe this could be your problem:
Button2.ID = "Button1";
According to the MSDN Documentation setting Control.ID will "provide you with programmatic access to the server control's properties, events, and methods.". You literally seem to assign Button1 to Button2, making Button2 fire the event subscribed by Button1.
Remove the Button2.ID line and I think it should work.
If it still doesn't work I recommend you to look through the .Designer.cs file and see if you've subscribed to the Button2_Click event.

.net thread safe many clicks at button

I have event
button.Click += ProcessClick;
and my event handler ProcessClick is:
private void async ProcessClick(object o, EventArgs e){
await LongOperation()
}
When I will click button quickly many times,
How to process only the first thread and skip other threads, until the first is done?
Disabling button after first click is not a solution...
EDIT: utilizing any type of thread constructions is acceptable: Tasks, Semaphores, locks and so on.
You can remove the event after the first click and add it again at the end of processing the first click.
private async void button1_Click(object sender, EventArgs e)
{
Debug.Write("Running click event");
this.button1.Click -= button1_Click;
await Task.Run(() => Task.Delay(5000));
this.button1.Click += button1_Click;
}
private bool longOperationRunning;
private void async ProcessClick(object o, EventArgs e){
if (longOperationRunning)
return;
longOperationRunning = true;
await LongOperation()
longOperationRunning = false;
}

pass method to event handler in C# WPF

This works in adding an event handler in C# WPF
CheckBox ifPrint = new CheckBox();
ifPrint.AddHandler(CheckBox.ClickEvent, new RoutedEventHandler(
(sender, e) => //toggle check box event
{
//do stuff
}));
but it looks messy when the method body gets long, so I want to define the method elsewhere like this
ifPrint.AddHandler(CheckBox.ClickEvent, delegate(object sender, RoutedEventArgs e){
checkBoxClick(sender, e);
});
private void checkBoxClick(object sender, RoutedEventArgs e)
{
//do stuff
}
but this doesn't even compile with the error: Cannot convert anonymous type to type 'System.Delegate' because it is not a delegate type
Sorry, I am new to this and have no idea how it's supposed to be done. Is this even close? Thanks!
You can subscribe to a separate method like this, as long as the signature of checkBoxClick is correct:
ifPrint.Click += checkBoxClick;
You can also subscribe to an event inline like this:
ifPrint.Click += (s, e) => SomeMethod();
Which then allows you to name your method something more reasonable and not require it to accept parameters:
private void SomeMethod()
{
//do stuff
}
Just to explain it a little further, in the above code, s and e take the place of the parameters in your checkBoxClick event method, so it's basically equivalent to this:
ifPrint.Click += checkBoxClick;
private void checkBoxClick(object sender, RoutedEventArgs e)
{
SomeMethod();
}
Edit, in regards to your comment.
Given this is much simpler, when, if ever, should one use this? ifPrint.AddHandler(CheckBox.ClickEvent, new RoutedEventHandler( (sender, e) => { //do stuff }));
I honestly don't think I've ever used that syntax.
It seems that in most cases it does the same thing. According to the MSDN docs, there's a handledEventsToo parameter on the AddHandler() method, which I think could be significant.
Imagine you subscribed to an event multiple times, like this:
ifPrint.Click += checkBoxClick;
ifPrint.Click += checkBoxClick;
ifPrint.Click += checkBoxClick;
And inside your event, you set e.Handled = true. If you didn't have that line, you'd see the message box displayed 3 times. But with that line, you only get the message box once, because the first time the event fires, it marks the event "handled".
private void checkBoxClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Clicked!");
e.Handled = true;
}
By passing in true for the last parameter (it's false by default), you actually tell it to fire that event, even if other events already "handled" the event.
ifPrint.AddHandler(CheckBox.ClickEvent,
new RoutedEventHandler((s, e) => { /* do stuff */ }), true);
try this logic to attach click event handler for your checkbox.
CheckBox ifPrint = new CheckBox();
ifPrint.Click+=checkBoxClick;
private void checkBoxClick(object sender, RoutedEventArgs e)
{
//do stuff
}

Can I assign a method to multiple Form-based Events?

I'm constructing a Form and it has several numericUpDown controls, several checkbox controls and some text boxes etc. Each control has a event method (CheckedChanged, ValueChanged etc) that is triggered that does something but my main quesiton is this:
What I want to do is run a single method which will update a text field on my form but currently I have it just repeated 24 times. This works but I feel there must be a better way ... Below is an example of what I have so far.
private void button3_Click(object sender, EventArgs e)
{
// Code Specific to the Buton3_Click
UpdateTextLabel();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
// Code Specific to the checkBox1_CheckChanged
UpdateTextLabel();
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
// numericUpDown1 specific code ....
UpdateTextLabel();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// comboBox1 specific stuff ...
UpdateTextLabel();
}
// .... and so on for every method ....
Is there a better way to achieve this? I want to say "if any control is clicked or changed ... DO THIS "UpdateTextLabel()" thing " but not sure how to go about it. Happy to be directed to the answer as the questions I typed into search didn't seem to be the "right questions" ...
Thanks!
yes, any events of any controls can share the same event handler method as long as their event handler delegates are the same, in this case, the event handler delegates of those controls are all of type "EventHandler" (no return value and 2 arguments: object sender and EventArgs e).
private void UpdateTextLabel(object sender, EventArgs e)
{
//your original UpdateTextLabel code here
}
button3.Click += UpdateTextLabel;
checkBox1.CheckedChanged += UpdateTextLabel;
numericUpDown1.ValueChanged += UpdateTextLabel;
comboBox1.SelectedIndexChanged += UpdateTextLabel;
For sure! You can use lambdas to easily deal with the unused arguments:
button3.Click += (sender, args) => UpdateTextLabel();
checkBox1.CheckedChanged += (sender, args) => UpdateTextLabel();
numericUpDown1.ValueChanged += (sender, args) => UpdateTextLabel();
comboBox1.SelectedIndexChanged += (sender, args) => UpdateTextLabel();
Or as some developers are trending, if you don't care about the args, you can use underscores to "ignore" them for readability:
button3.Click += (_, __) => UpdateTextLabel();
checkBox1.CheckedChanged += (_, __) => UpdateTextLabel();
numericUpDown1.ValueChanged += (_, __) => UpdateTextLabel();
comboBox1.SelectedIndexChanged += (_, __) => UpdateTextLabel();
As the mighty Jon Skeet once schooled me, this is far superior to the default Visual Studio naming scheme of CONTROLNAME_EVENTNAME as you can easily read "when button 3 is clicked, update the text label", or "when the combobox is changed, update the text label". It also frees up your code file to eliminate a bunch of useless method wrappers. :)
EDIT: If you have it repeated 24 times, that seems a bit odd from a design standpoint. ... reads again Oh darn. I missed the comments, you want to run specific code as well as update the text box. Well, you could register more than one event:
button3.Click += (_, __) => SubmitForm();
button3.Click += (_, __) => UpdateTextLabel();
The problem with this, is technically, event listeners are not guaranteed to fire in-order. However, with this simple case (especially if you don't use -= and combine event handlers) you should be fine to maintain the order of execution. (I'm assuming you require UpdateTextLabel to fire after SubmitForm)
Or you can move the UpdateTextLabel call into your button handler:
button3.Click += (_, __) => SubmitForm();
private void SubmitForm(object sender, EventArgs e)
{
//do submission stuff
UpdateTextLabel();
}
Which kinda puts you into the same boat (albeit with better method naming). Perhaps instead you should move the UpdateTextLabel into a general "rebind" for your form:
button3.Click += (_, __) => SubmitForm();
private void SubmitForm(object sender, EventArgs e)
{
//do submission stuff
Rebind();
}
private void Rebind()
{
GatherInfo();
UpdateTextLabel();
UpdateTitles();
}
This way if you have to do additional work besides just updating a text label, all your code is calling a general Rebind (or whatever you want to call it) and it's easier to update.
EDITx2: I realized, another option is to use Aspect Oriented Programming. With something like PostSharp you can adorn methods to execute special code which gets compiled in. I'm 99% sure PostSharp allows you to attach to events (though I've never done that specifically):
button3.Click += (_, __) => SubmitForm();
[RebindForm]
private void SubmitForm(object sender, EventArgs e)
{
//do submission stuff
}
[Serializable]
public class RebindFormAttribute : OnMethodBoundaryAspect
{
public override void OnSuccess( MethodExecutionArgs args )
{
MyForm form = args.InstanceTarget as MyForm; //I actually forgot the "InstanceTarget" syntax off the top of my head, but something like that is there
if (form != null)
{
form.Rebind();
}
}
}
So even though we do not explicitly make a call anywhere to Rebind(), the attribute and Aspect Oriented Programming ends up running that extra code OnSuccess there whenever the method is invoked successfully.
Yes, you don't want to write code like this. You don't have to, the Application.Idle event is ideal to update UI state. It runs every time after Winforms retrieved all pending messages from the message queue. So is guaranteed to run after any of the events you currently subscribe. Make it look like this:
public Form1() {
InitializeComponent();
Application.Idle += UpdateTextLabel;
this.FormClosed += delegate { Application.Idle -= UpdateTextLabel; };
}
void UpdateTextLabel(object sender, EventArgs e) {
// etc..
}

Changing the function of a button click?

I know the answer is probably really obvious, but I'm having a complete brain fart here.
What I want to do is have a simple form with two buttons. The first button shows a message saying "1". After clicking the second button, the first button says "2" when clicked. After clicking the second button again, it goes back to saying "1".
Having learned programming with javascript, I'm still thinking in javascript. My first train of thought was:
myButton.onclick=...
After that the only thing I could think of was to have a conditional inside the first button's click function and use the second button's click to change a boolean...
Is there a better way to do this?
Make button2 change the method which is called when button1 is clicked:
private void button1_Click(object sender, EventArgs e)
{
Text = "1";
}
private void button1_Click2(object sender, EventArgs e)
{
Text = "2";
button1.Click -= button1_Click2;
button1.Click += button1_Click;
}
private void button2_Click(object sender, EventArgs e)
{
button1.Click -= button1_Click;
button1.Click += button1_Click2;
}
I understood, what happens when one click the button2 first time and for the second time. But if you want to say that its the pattern it has to follow, then:
Bool bln = true;
private void button2_Click(object sender, EventArgs e)
{
if(bln)
text1();
else
text2();
bln = !bln;
}
private void text1()
{
// Whatever
}
private void text2()
{
// Whatever
}
Populate the method with whatever you are looking for. In this, These methods can be reused for button1 click event also.
Hope it helps.
Have the second button's click handler set a message variable, and simply have the first button's click handler display it.
edit: I wrote this for asp.net. Converting to winforms shouldn't be difficult.
Declare a string variable:
public static mystring = "1";
on button2_click you can change that value. I am showing the simple case of changing it once permanently, but you can write code to alternate in any way you like:
protected void btn2_Click(object sender, EventArgs e)
{
mystring = "2";
}
For example, to alternate between 1 and 2, you can set the value of int n = 1, and have btn2 set the value to (3-n).ToString();
Then do:
protected void btn1_Click(object sender, EventArgs e)
{
Response.Write(mystring);
}
You have to do myButton.onclick-=function_name
+= is to add function
-= is to remove function
You can always make it work this way:
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "Button 1 Text";
MessageBox.Show("B1 Function1");
button1.Click -= button1_Click;
button1.Click += button1_Click2;
}
private void button1_Click2(object sender, EventArgs e)
{
button.Text = "Button 1 Text 2";
MessageBox.Show("B1 Function2");
button1.Click -= button1_Click2;
button1.Click += button1_Click;
}

Categories

Resources