C#如何:尝试在同一个班级中调用两次按钮?

时间:2009-06-30 12:56:36

标签: c# winforms

在这里进行了一些搜索&在网上还没有找到一个好的答案。我要做的是在C#中的同一个类中调用两次按钮。

这是我的情景 -

我有一个带有“Go”按钮的表单。当我第一次点击它时,它会通过一些'for'循环(不停)来显示颜色范围。同时我将button1.Text属性设置为“Stop”。我希望能够第二次点击按钮,当发生这种情况时,我希望程序停止。基本上是一个走走停停的按钮。我知道如何使用2个按钮事件,但想使用1个按钮。

现在,结束程序的唯一方法是表单上的X按钮。

到目前为止,我尝试了不同的东西并且没有太多运气,所以想在这里询问大师如何去做。

顺便说一句,这是对 Head First Labs C#书籍练习的修改。

谢谢!

〜阿伦

7 个答案:

答案 0 :(得分:7)

您需要使用多线程(在单独的线程中异步启动进程密集型代码),例如,使用.NET 2+中的BackgroundWorker对象。这是必要的,因为在完成Start方法中运行的循环之前,UI不会响应用户的单击。如果您使用相同的按钮或另一个按钮来切换过程,则无关紧要,因为处理器正忙于处理循环。

BackgroundWorker有一个名为WorkerSupportsCancellation的属性,在这种情况下需要为true。当用户单击“停止”时,您将调用CancelAsync的{​​{1}}方法。

请参阅MSDN以获取一个好例子。另外DreamInCode有一个很好的教程,看起来非常类似于你的要求。

答案 1 :(得分:3)

为什么不创建两个按钮,当另一个可见时隐藏一个按钮?这应该更容易处理。

或者您可以添加一个bool字段来指示要执行的操作分支。

答案 2 :(得分:3)

一个简单的解决方案是在表单中添加一个布尔成员,例如,当按钮显示“Go”时为true,当按钮显示为“Stop”时为false

然后,在按钮的事件处理程序中,检查该布尔值。如果值为true,则在您将按钮的文本更改为“停止”时,启动操作并将值设置为false。反之亦然。 :)

如果这是生产代码,我可能更喜欢其他技术,可能包括更仔细地考虑表单的设计,但由于这显然是一个学习练习,我相信一个简单的布尔标志,指示当前的状态表格正是您所需要的。

请注意,我强烈建议您不要检查按钮文本的值以确定对象所处的状态。只要有可能,作为良好设计的一般规则,您希望您的视觉状态与您的“解耦”基础对象的状态。也就是说,您的可视窗口小部件可以依赖于您的底层对象,但您的底层对象不应该依赖于您的可视窗口小部件。如果您测试了按钮的文本,那么您的基础逻辑将取决于您的视觉状态,这将违反此一般规则。

如果您的问题与您在执行操作时无法取消操作有关,那么您需要考虑使用BackgroundWorker来执行长时间运行的活动。

答案 3 :(得分:1)

另一种选择是检查按钮上的当前文本以确定要执行的操作:

void btnStartStop_Click(Object sender, EventArgs e) 
{
    if (btnStartStop.Text == "Go")
    {
        btnStartStop.Text = "Stop";

        // Go code here

    }
    else 
    {
        btnStartStop.Text = "Go";

        // Stop code here

    }
}

答案 4 :(得分:1)

您是否获得了第二次按键点击活动?在您的点击处理程序中放置一个断点并运行您的代码。当你第二次点击时,你有没有碰到你的断点?

如果您的循环连续运行,并且它位于您的按钮单击处理程序中,那么您的循环将在UI线程中运行。在循环完成之后,您可能无法“看到”第二个按钮单击。除了上面看到的分支代码之外,尝试在循环处理中插入一个DoEvents(这是一个你的循环暂时放弃控制以便可以处理消息的地方)。或者,(更好)查看backgroundworker类 - 在不同的线程中执行大部分处理,以便UI可以保持对按钮点击的响应。

答案 5 :(得分:1)

Cerebrus是关于使用Background Worker线程的。但是,如果您正在执行WPF应用程序,则它将无法直接更新UI。要解决此问题,您可以在主控制/窗口上调用Dispatcher.BeginInvoke

给出如下代码:

Private Delegate Sub UpdateUIDelegate(<arguments>)

Private Sub CallUpdateUI(<arguments>)
  control.Dispatcher.BeginInvoke(Windows.Threading.DispatcherPriority.Background, New UpdateUIDelegate(AddressOf UpdateUI), <arguments>)
End Sub

Private Sub UpdateUI(<arguments>)
  'update the UI
End Sub

您可以从后台工作线程调用CallUpdateUI,它将获得执行UpdateUI的主线程。

答案 6 :(得分:0)

您可以将按钮上的Tag属性设置为布尔值,指示下一个操作应该是“停止”还是“开始”,并在每次单击按钮时重置它。但它是一个Object属性,所以当你阅读它时你必须将它强制转换为bool。