创建和调用另一个方法内的按钮来修改

时间:2014-03-05 20:50:29

标签: c# object button methods

我对C#(以及一般的编程)相当新,所以如果可以,请尽量详细说明。我试图搜索这个但无法找到答案。我有一个有10个按钮的表单。在每次单击按钮时,我将在最初执行相同的操作,例如启动进度条并禁用按钮,直到按钮方法完成。然后我将再次启用该按钮并禁用进度条。所以我的问题是,如何创建一个允许我为任何变量方法执行相同功能的通用方法?例如:

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;
}

因此,在上面的示例中,我想编写一个通用方法,根据单击的方法禁用btnOne,btnTwo,btnThree或btnFour。同样重新启用按钮。

我知道我可以让它工作这样做,但它看起来效率不高,因为我一遍又一遍地重写相同的代码:

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;}

5 个答案:

答案 0 :(得分:1)

您只需编写一个接受按钮的方法:

private void DoTheButtonStuff(Button button)
{
    button.Enabled = false;
    progressBar.Visible = true;

    // Do stuff here

    button.Enabled = true;
    progressBar.Visible = false;
}

请记住,除非您在分离的线程上执行任务,否则实际上看不到按钮禁用/启用和进度条更新。实质上,接口将被冻结,直到任务完成。您可以运行Application.DoEvents()来更新接口,但这会引入另一组问题。

答案 1 :(得分:0)

编辑:这是完整的解决方案(适用于2个按钮)。您必须将每个按钮的Click事件设置为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;
        }

    }

答案 2 :(得分:0)

您有几个选项,具体取决于Some statements here的含义。

如果所有陈述都相同,那么你可以这样做:

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;
}

并且,在您的表单中,指定每个按钮的单击事件以转到该方法。

如果每个按钮的Some statements here不同,您可以这样做:

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;
}

希望有帮助

答案 3 :(得分:0)

您需要处理每个按钮的点击事件。下面的示例为所有按钮创建单个事件处理程序。

有关按钮点击事件的详细信息,请参阅this link

为简单起见,我会为每个按钮创建一个新的事件处理程序。这样,您就可以处理该按钮的特定进度条。

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; 
}

答案 4 :(得分:0)

对于WinForms应用程序:

如前所述,您希望在后台线程中完成工作。在UI线程上执行此操作会“冻结”屏幕,这将使用户看不到禁用/重新启用。

概括启用/禁用

private void isEnabled(Button btn, bool _bool)
{
    btn.Enabled = _bool;
}

您还需要创建一个单独的方法,使进度条可见/不可见。这将用于对UI线程进行线程安全调用,如下所述。

private void isVisible(bool _bool)
{
    progressBar1.Visible = _bool;
}

然后,您需要确保在后台线程上运行任务。您可以按如下方式创建单击事件处理程序:

private void btn_Click(object sender, EventArgs e)
{
    //Sender is the button that was clicked
    ThreadPool.QueueUserWorkItem(PerformTasks, sender);
}

因为您将使用后台线程,所以您需要创建委托以使线程安全调用回UI线程。

private delegate void ButtonDelegate(Button btn, bool isEnabled);
private delegate void ProgressBarDelegate(bool isVisible);

最后,你的代码的工作马。此方法在后台运行,并在作业启动和完成时使线程安全调用回UI线程。

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;
    }

}

有关在WinForms中进行线程安全调用的更多信息,请参阅以下msdn article