我对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;}
答案 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。