Reputation: 3
I'm fairly new to C# (and programming in general), so please try to be detailed if you can. I tried to search for this but unable to find an answer. I have a form with 10 buttons. On each button click, I'm going to do the same thing initially, such as start a progress bar and disable the button until the button methods have been completed. Then I'll enable the button again and disable the progress bar. So my question is, how can I create a general method that allows me to do the the same function for any variable method? Example:
private void btnOne() {disableButton(); some statements here; enableButton()}
private void btnTwo() {disableButton(); some statements here; enableButton()}
private void btnThree() {disableButton(); some statements here; enableButton()}
private void btnFour() {disableButton(); some statements here; enableButton()}
private void disableButton()
{
this.button.Enabled = false;
progressBar.Visible = true;
}
private void enableButton()
{
this.button.Enabled = true;
progressBar.Visible = false;
}
So in the example above, I want to write one universal method that disables btnOne, btnTwo, btnThree, or btnFour, based on which one was clicked. Same for re-enabling the button.
I know I can get it to work doing this but it doesn't look efficient since I'm rewriting the same code over and over:
private void btnOne()
{btnOne.Enabled = false; some statements here; btnOne.Enabled = true;}
private void btnTwo()
{btnTwo.Enabled = false; some statements here; btnTwo.Enabled = true;}
private void btnThree()
{btnThree.Enabled = false; some statements here; btnThree.Enabled = true;}
private void btnFour()
{bthFour.Enabled = false; some statements here; bthFour.Enabled = true;}
Upvotes: 0
Views: 1440
Reputation: 1447
EDIT: Here is the complete solution (for 2 buttons). You have to set the Click
event for each button to be btn_Click
private void btn_Click(object sender, EventArgs e) {
Button btn = (Button)sender;
btn.Enabled = false;
MyBackgroundWorker bgw = new MyBackgroundWorker(btn);
if (btn == btnOne) {
bgw.DoWork += bgw_DoWork_One;
} else if (btn == btnTwo) {
bgw.DoWork += bgw_DoWork_Two;
}
//...
bgw.RunWorkerAsync(); // button enabled when completed
}
private void bgw_DoWork_One(object sender, DoWorkEventArgs e) {
// button 1 statements
}
private void bgw_DoWork_Two(object sender, DoWorkEventArgs e) {
// button 2 statements
}
public class MyBackgroundWorker : BackgroundWorker {
protected Button btn;
public MyBackgroundWorker(Button btn) : base() {
this.btn = btn;
this.btn.Enabled = false;
this.RunWorkerCompleted += bgw_RunWorkerCompleted;
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
btn.Enabled = true;
}
}
Upvotes: 0
Reputation: 11
For a WinForms app:
As has been mentioned, you'd want to do your work in a background thread. Doing it on the UI thread would 'freeze' the screen which will make the disabling/re-enabling invisible to the user.
To generalize the Enabling/disabling
private void isEnabled(Button btn, bool _bool)
{
btn.Enabled = _bool;
}
You'll also need to create a separate method for making the progress bar visible/invisible. This will be used to make thread safe calls to the UI thread as explained below.
private void isVisible(bool _bool)
{
progressBar1.Visible = _bool;
}
You would then want to make sure you run your tasks on a background thread. You can create a single click event handler as follows:
private void btn_Click(object sender, EventArgs e)
{
//Sender is the button that was clicked
ThreadPool.QueueUserWorkItem(PerformTasks, sender);
}
Because you will be working with a background thread, you will need to create delegates to make thread safe calls back to the UI thread.
private delegate void ButtonDelegate(Button btn, bool isEnabled);
private delegate void ProgressBarDelegate(bool isVisible);
Finally, the work horse of your code. This method runs in the background and makes thread safe calls back to the UI thread when the job starts and completes.
private void PerformTasks(object obj)
{
//The passed in obj is the sender, in our case the clicked button
Button btn = obj as Button;
ButtonDelegate delButton = new ButtonDelegate(isEnabled);
ProgressBarDelegate delProgressBar = new ProgressBarDelegate(isVisible);
//Make a thread safe call to disable button and make progressbar visible
if (this.InvokeRequired)
{
btn.Invoke(delButton, btn, false);
progressBar1.Invoke(delProgressBar, true);
}
else
{
btn.Enabled = false;
progressBar1.Visible = true;
}
switch (btn.Name)
{
case "button1":
//Code to run in background for button 1
//alternatively, for organization/debugging purposes
//create a sub method
break;
case "button2":
//case 2
break;
//... more cases
}
//Make a thread safe call to re-enable button and make progress bar invisible
if (this.InvokeRequired)
{
btn.Invoke(delButton, btn, true);
progressBar1.Invoke(delProgressBar, false);
}
else
{
btn.Enabled = true;
progressBar1.Visible = false;
}
}
For more information on making thread safe calls in WinForms see the following msdn article.
Upvotes: 0
Reputation: 1240
You need to handle the click events of each button. The example below creates a single event handler for all buttons.
For more info on button click events, see this link.
For simplicity, I would create a new event handler for each button. That way, you can handle that button's specific progress bar.
btnOne.Click += new EventHandler(this.HandleButtonClick);
btnTwo.Click += new EventHandler(this.HandleButtonClick);
btnThree.Click += new EventHandler(this.HandleButtonClick);
protected void HandleButtonClick(object sender, EventArgs e)
{
Button clickedButton = (Button)sender;
clickedButton.Enabled = false;
...
clickedButton.Enabled = true;
}
Upvotes: 0
Reputation: 4593
You have a few options, depending on what Some statements here
means.
If all the statements will be the same then you can do this:
public void HandleButtonClick(object sender, EventArgs e)
{
(sender as Button).Enabled = false;
progressBar.Visible = true;
//Some statements
progressBar.Visible = false;
(sender as Button).Enabled = true;
}
And, in your form, designate the click event of each button to go to that method.
If Some statements here
is different for each button, you can do this:
private void btnOne(object sender, EventArgs e) //Do this for each button
{
ChangeVisualState(sender as Button, false);
//Statements
ChangeVisualState(sender as Button, true);
}
public void ChangeVisualState(Button btn, bool buttonState)
{
btn.Enabled = buttonState;
progressBar.Visible = !buttonState;
}
Hopefully that helps
Upvotes: 0
Reputation: 19496
You would just write a method that accepts a button:
private void DoTheButtonStuff(Button button)
{
button.Enabled = false;
progressBar.Visible = true;
// Do stuff here
button.Enabled = true;
progressBar.Visible = false;
}
Keep in mind though, that unless you're performing the tasks on a separated thread, the button disable/enable and the progress bar updates won't actually be seen. The interface will, in essence, be frozen until the task is finished. You could run Application.DoEvents()
to get the interface to update, but that introduces another set of problems.
Upvotes: 1