如何从Button Click事件中获取返回值?

BBB*_*BBB 3 c# winforms

我刚开始学习C#.我看到一个老问题,有人试图制作可口可乐机器,这似乎是一个很好的练习.

但我陷入了金钱按钮.我无法弄清楚如何存储按钮在变量中所代表的金额,可通过ColaMachine方法访问.

我有以下代码:

using System;
using System.Windows.Forms;
using System.Drawing;

namespace QuickSharp
{
    public class ColaMachine : Form
    {
        public ColaMachine()
        {
            this.Text = "Cola Machine";
            this.Size = new Size(450 , 500);

            //Money & Money Buttons   

            Label Money;
            Money = new Label();
            Money.Text = "Insert Coins Here:";
            Money.Location = new Point(20, 100);
            this.Controls.Add(Money);

            Button MoneyButton1;
            MoneyButton1 = new Button();
            MoneyButton1.Text = "€0,05";
            MoneyButton1.Location = new Point(28,125);
            MoneyButton1.Click += new System.EventHandler(this.MoneyButton1_Click);
            this.Controls.Add(MoneyButton1);

            Button MoneyButton2;
            MoneyButton2 = new Button();
            MoneyButton2.Text = "€0,10";
            MoneyButton2.Location = new Point(28,165);
            MoneyButton2.Click += new System.EventHandler(this.MoneyButton2_Click);
            this.Controls.Add(MoneyButton2);

            Button MoneyButton3;
            MoneyButton3 = new Button();
            MoneyButton3.Text = "€0,20";
            MoneyButton3.Location = new Point(28,205);
            MoneyButton3.Click += new System.EventHandler(this.MoneyButton3_Click);
            this.Controls.Add(MoneyButton3);

            Button MoneyButton4;
            MoneyButton4 = new Button();
            MoneyButton4.Text = "€0,50";
            MoneyButton4.Location = new Point(28,245);
            MoneyButton4.Click += new System.EventHandler(this.MoneyButton4_Click);
            this.Controls.Add(MoneyButton4);

            Button MoneyButton5;
            MoneyButton5 = new Button();
            MoneyButton5.Text = "€1,00";
            MoneyButton5.Location = new Point(28,285);
            MoneyButton5.Click += new System.EventHandler(this.MoneyButton5_Click);
            this.Controls.Add(MoneyButton5);

            Button MoneyButton6;
            MoneyButton6 = new Button();
            MoneyButton6.Text = "€2,00";
            MoneyButton6.Location = new Point(28,325);
            MoneyButton6.Click += new System.EventHandler(this.MoneyButton6_Click);
            this.Controls.Add(MoneyButton6);

            // Drinks & Drink Buttons

            Label Drinks;
            Drinks = new Label();
            Drinks.Text = "Choose Your Drink:";
            Drinks.Location = new Point(315 , 100);
            Drinks.AutoSize = true;
            this.Controls.Add(Drinks);

            Button DrinkButton1;
            DrinkButton1 = new Button();
            DrinkButton1.Text = "Coca-Cola";
            DrinkButton1.Location = new Point(328,125);
            this.Controls.Add(DrinkButton1);

                        Button DrinkButton2;
            DrinkButton2 = new Button();
            DrinkButton2.Text = "Coca-Cola Light";
            DrinkButton2.Location = new Point(328,165);
            this.Controls.Add(DrinkButton2);

                        Button DrinkButton3;
            DrinkButton3 = new Button();
            DrinkButton3.Text = "Fanta";
            DrinkButton3.Location = new Point(328,205);
            this.Controls.Add(DrinkButton3);

                        Button DrinkButton4;
            DrinkButton4 = new Button();
            DrinkButton4.Text = "Sprite";
            DrinkButton4.Location = new Point(328,245);
            this.Controls.Add(DrinkButton4);

                        Button DrinkButton5;
            DrinkButton5 = new Button();
            DrinkButton5.Text = "Spa Blauw";
            DrinkButton5.Location = new Point(328,285);
            this.Controls.Add(DrinkButton5);

                        Button DrinkButton6;
            DrinkButton6 = new Button();
            DrinkButton6.Text = "Red Bull";
            DrinkButton6.Location = new Point(328,325);
            this.Controls.Add(DrinkButton6);

            //Header & Machine Display

            Label Header;
            Header = new Label();
            Header.Text = "Coca-Cola Machine";
            Header.Font = new Font("Arial" , Header.Font.Size +5);
            Header.ForeColor = Color.DarkRed;
            Header.Location = new Point(132, 20);
            Header.AutoSize = true;
            this.Controls.Add(Header);



            TextBox TextBox1 ;
            TextBox1 = new TextBox();

            if(InsertedCoins == 0.00)
                TextBox1.Text = "Buy Your Ice Cold Drinks Here!";
            else
                TextBox1.Text = "Inserted Coins: €" + InsertedCoins;

            TextBox1.BackColor = Color.Black;
            TextBox1.ForeColor = Color.Red;
            TextBox1.Font = new Font("Arial" , TextBox1.Font.Size +3);
            TextBox1.ReadOnly = true;
            TextBox1.Size = new Size(210,300);
            TextBox1.Location = new Point(112,50);

            // I tried to get the text scrolling here... :)
            TextBox1.SelectionStart = TextBox1.Text.Length;
            TextBox1.ScrollToCaret();
            TextBox1.Refresh();

            this.Controls.Add(TextBox1);
        }


        public double InsertedCoins;

        // Money Button Click Events

        private void MoneyButton1_Click(object sender, EventArgs e)
        {
            InsertedCoins = InsertedCoins + 0.05;
        }

        private void MoneyButton2_Click(object sender, EventArgs e)
        {
            InsertedCoins = InsertedCoins + 0.10;
        }

        private void MoneyButton3_Click(object sender, EventArgs e)
        {
            InsertedCoins = InsertedCoins + 0.20;
        }

        private void MoneyButton4_Click(object sender, EventArgs e)
        {
            InsertedCoins = InsertedCoins + 0.50;
        }

        private void MoneyButton5_Click(object sender, EventArgs e)
        {
            InsertedCoins = InsertedCoins + 1.00;
        }

        private void MoneyButton6_Click(object sender, EventArgs e)
        {
            InsertedCoins = InsertedCoins + 2.00;
        }

        private static void Main()
        {

            ColaMachine Scherm;
            Scherm = new ColaMachine();
            Application.Run(Scherm);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,如果您对我的一般编程有任何提示(例如,为了让其他人试图阅读我的代码更容易理解),请告诉我!

rad*_*bob 6

当我想到可乐机器时,我看到机器中每种饮料的按钮,但不是用于不同金额的按钮.也许你的意思是一个焦炭花费50美分所以按下我需要收取50美分的可乐按钮.

按钮和事件处理程序

当您按下屏幕上的按钮时,它会生成一个单击事件.您需要编写一个方法来响应该单击.我们用来响应事件的任何方法(一般来说)都称为事件处理程序.您必须告诉您的程序哪些按钮与哪些事件处理程序一起使用.我们称之为注册事件处理程序

按照惯例,如果您的按钮名为"CokeButton",则与该特定按钮关联的事件处理程序将命名为"CokeButton_ClickHandler".或类似的东西.

一般建议

想想你正在建模的东西,并在代码中定义事物以反映现实世界.模型中的东西通常最终会成为类,类属性和类字段.这些事情通常最终会成为适当类别中的方法.然后你想想这些事情是如何相互作用的.

在开始编写代码之前,您不需要弄清楚可乐机器的所有内容.你应该一次写一点点,测试那些,然后建立在你测试的东西上.不要编写复杂的交互代码然后进行测试.你最终会在追逐你的尾巴的圈子里旋转.写一点,测试一下,重复一遍.现在听我说,以后相信我; 写一点,测试一下,重复一遍.现在和永远听从这个建议.

所以这就是我对可乐机器的看法.首先是焦炭机本身.

public class CokeMachine {}
Run Code Online (Sandbox Code Playgroud)

可乐机具有钱槽,返回槽和饮料按钮.我真的不能把钱放在一个插槽中,所以手边,我会说我会输入一个文本框.然后我会点击一个按钮,焦炭会分配.我觉得我已经定义了足够的模型来开始.关于可乐机器还有很多其他的东西,但我现在不会担心它们.

但我需要知道每种饮料的成本.

好吧,好吧.那么必须有"CokeCost","7UpCost"等字段.所以定义它们!我们将随时了解如何以及在何处使用它们.

   public class CokeMachine {
     Button Coke;
     Button 7Up;
     Button RootBeer;
     TextBox MoneySlot;

     double CokeCost = .75;
     double 7UpCost = .65;
}
Run Code Online (Sandbox Code Playgroud)

我说按钮需要处理程序,所以我们至少可以编写一些代码shell.我希望他们都能以同样的方式工作,所以我现在专注于一个.请注意,在编写代码时,我意识到必须处理的其他事情.我会发表评论,调用尚不存在的方法等.

   public class CokeMachine {
     Button Coke;
     Button 7Up;
     Button RootBeer;
     TextBox MoneySlot;

     double CokeCost = .75;
     double 7UpCost = .65;

     // "wiring up" the coke button click event to it's handler.
     // We do this in C# by declaring an new EventHandler object (a .NET framework supplied class)
     // and we pass in the name of our method as a parameter.
     // This new EventHandler is *added* to the button's click event.
     // An event can have multiple handlers, that's why we do "+="
     // instead of just "=". Otherwise we would have accidentally "unhooked" any
     // previously registered handlers.
     Coke.Click += new EventHandler(Coke_ClickHandler);

     // this is the .NET event handler method signature.
     Public void Coke_ClickHandler (object sender, EventArgs args){
          if (MoneySlot.Value >= CokeCost) {
             DispenseDrink();
             // How do I handle returning change? Maybe DispenseDrink() can do that.
          }else {
             // tell customer to put in more money
          }
     }

     private void DispenseDrink() {
       // An empty method is enough to get it to compile so for now that's fine.
       // I need to test the Coke_EventHandler logic that I've written so far.
     }

  }
Run Code Online (Sandbox Code Playgroud)

现在我需要测试到目前为止我写的内容.在那之后,我需要决定下一步要关注什么.但是要意识到,当你编写依赖于已编写代码的新代码时,如果现有代码尚未经过测试 - 现在你看到了错误,那么你自己就更难了.您可以在代码更简单时进行测试.现在还有更多,它更复杂,并且将更难调试和修复.

建议,第二部分

冒着把事搞砸的风险,我按照原来的答案提出这个问题:

你可以看到每个饮料按钮都做同样的事情,并且考虑到上面的代码,我们会为每个按钮一遍又一遍地编写相同的逻辑.如果有什么需要改变,我们必须在任何地方改变它.

更多一般建议

一个面向对象的Progamming启发式封装了保持不变的内容.你应该一直在寻找可能成为公共代码候选者的地方.

我想强调的是,这种常见的按钮行为对我来说并不是很明显.只有在我编写完上面的代码之后,我才开始认为所有的饮料按钮处理程序都会看起来一样,我意识到在真正的饮料机器上,它们实际上的行为方式相同.我的编码spidey-sense告诉它,当代码反映你真实事物的可识别行为(双关语意图!)时,这绝对是件好事.

重构

实际上是一个技术术语,意味着重新编写现有代码,使其更灵活,可重复使用,可读等.总之,可维护.

重构应始终在您的思维过程中.但请确保您有合理的理由进行任何更改.重塑代码是软件开发中不可或缺的一部分.

让我们通过提取方法来重构

     Public void Coke_ClickHandler (object sender, EventArgs args){
          PurchaseDrink("Coke", CokeCost);
     }

     // now we have a method that stands out and says THIS is how it works
     // and a single point of change, rather than ump-teen button handlers.
      private PurchaseDrink (string whatKind, double cost) {

         // all I did so far is move the code and change "Cokecost" to "cost"
         // Now I'm beginning to think I may need to pass "whatKind" to
         // DispenseDrink() - but first I need to test the changes I've
         // made at this level.
         // ***** and since I already tested the code when I 1st wrote it,
         // this refactoring will be easier & quicker to test.. GET IT??!! ******

         if (MoneySlot.Value >= cost) {
             DispenseDrink();
             // How do I handle returning change? Maybe DispenseDrink() can do that.
          }else {
             // tell customer to put in more money
          }
     }

     private void DispenseDrink() {
       // An empty method is enough to get it to compile so for now that's fine.
       // I need to test the Coke_EventHandler logic that I've written so far.
     }
Run Code Online (Sandbox Code Playgroud)

枚举

我讨厌使用字符串,就像我上面使用"可乐"一样.错字和套管(上/下,即)会导致Visual Studio无法捕获的问题.当我有一个有限的东西 - 各种饮料 - 我真的喜欢使用枚举.它们出现在intellesense中,我可以在switch语句中使用它们(并研究"类型安全"的概念).我真正喜欢的是,他们绝对在一个地方定义我们的程序所知道的所有饮料类型.这就像文档!