2012-03-11 55 views
1

我剛開始學習C#。我看到有人試圖製造可口可樂機器的老問題,這似乎是一個很好的練習。如何從Button Click事件中獲取返回值?

但我卡在錢按鈕。我無法弄清楚如何存儲按鈕在變量中表示的金額,可通過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); 
     } 
    } 
} 

另外,如果您對我的通用編程任何提示(如使事情更易於遵循別人想讀我的代碼),請告訴我!

+0

不是說你的情況真的很重要:在處理貨幣金額時,應該使用'decimal'類型而不是雙倍。這將防止舍入誤差,因爲小數類型是爲精確表示十進制數而開發的。 – ChrisWue 2012-03-11 02:10:19

回答

5

當我想到一臺可樂機時,我看到機器中每種飲料的按鈕,但不是按鈕的不同數量的金錢。也許你的意思是可樂的價格是50美分,所以按下可樂按鈕我需要收取50美分。

按鈕和事件處理

當您按下屏幕上的按鈕,它會生成一個click事件。您需要編寫一個方法來響應該點擊。我們用來響應事件的任何方法(通常來說)都稱爲事件處理程序。你必須告訴你的程序什麼事件處理程序按鈕。按照慣例,如果您的按鈕名爲'CokeButton',那麼與該特定按鈕關聯的事件處理程序將被命名爲'CokeButton_ClickHandler'。或類似的東西。

一般建議

想想你正在建模的事情,在代碼中定義的東西,以反映真實的世界。模型中的東西通常會以類,類屬性和類字段結尾。這些事情通常會以適當類別的方法結束。然後你想想這些事情是如何相互作用的。

在開始編寫代碼之前,您無需弄清楚的一切關於可樂機。你應該一次寫一點點,測試一下,然後建立在你測試過的東西上。不要編寫複雜的交互代碼,然後測試。你最終會繞着追逐尾巴的圈子旋轉。寫一點,測試一下,重複一遍。 現在就來聽我說,以後再相信我;寫一點,測試一下,重複一遍。現在和永遠留意這個建議。

所以這裏是我如何考慮可口可樂機。首先有一臺可樂機。

public class CokeMachine {} 

焦炭機有一個錢槽,一個返回插槽和飲料按鈕。我真的不能把錢放在一個槽中,所以我會說我會輸入一個文本框。然後我點擊一個按鈕,焦炭就會分配。我覺得我已經定義了足夠的模型來開始。關於可樂機還有很多其他的事情,但我現在不會爲它們擔心。

但我需要知道每個飲料的成本是多少。

好吧,好的。那麼就必須有「可口可樂」,「7UpCost」等字段。所以定義它們!隨着我們的進展,我們將弄清楚如何以及如何使用它們。

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

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

我說按鈕需要處理程序,所以我們至少可以編寫一些代碼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. 
    } 

    } 

現在我需要測試我迄今爲止所寫的內容。之後,我需要決定下一步要關注什麼。但要認識到,當你編寫依賴於已經編寫代碼的新代碼時,如果現有的代碼沒有經過測試 - 現在你看到了錯誤,那麼你已經讓自己變得更加困難。當代碼更簡單時,您可以測試。現在還有更多,它更復雜,並且將更難以調試和修復。

建議,第二部分

在搞亂東西的風險,我提供這個folow中,到了我原來的答覆:

你可以看到,每喝按鈕做同樣的事情,和考慮到上面的代碼,我們會爲每個按鈕反覆寫入相同的邏輯。如果有什麼需要改變,我們必須在任何地方改變它。

更一般建議

一個面向對象的預設電臺啓發式是封裝了其保持不變。你應該時刻注意可能會出現通用代碼的地方。

我想強調的是,這種常見的按鈕行爲對我而言並不是很明顯。只有在我寫了上面的代碼之後,我纔開始認爲我所有的飲料按鈕處理程序看起來都是一樣的,而且我意識到,在一臺真正的飲料機上,它們的行爲方式是一樣的。我的編碼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. 
    } 

枚舉

我討厭使用字符串我用上面的 「可樂」 的方式。 Typo和套管(上/下,即)會導致Visual Studio無法捕捉的問題。當我有一個有限的事情列表 - 各種飲料 - 我真的很喜歡使用枚舉。他們出現在intellesense中,我可以在switch語句中使用它們(並研究「類型安全」的想法)。而我真正喜歡的是,他們絕對在一個地方定義了我們的計劃知道的所有飲料類型。這就像文件!

+0

MoneyButtons表示您在機器中插入的硬幣。非常感謝,非常有幫助。我可能會完全重寫它。我和我的隧道視野... – 2012-03-11 02:56:00

3

可以存儲每個按鈕i按鈕標記屬性的數量,並在事件處理程序使用下面的代碼閱讀量:

void ValueButton_Click(object sender, EventArgs e) 
{ 
    Button button = sender as Button; 
    if (button == null) return; 
    if (button.Tag == null) return; 
    double amount = (double)button.Tag; 

    // Process the amount here.... 
    InsertedCoins += amount; 
} 
+0

謝謝!我還沒有理解所有的東西,但我會努力的。 – 2012-03-11 03:03:46

0

首先想到: 你應該劃分問題分爲兩類(課堂測試和課堂ColaMachine)。

它看起來像

public class ColaMachine : Form 
{ 
    public ColaMachine() 
    { 
    ... 
    } 
} 

public class Test 
{ 
    private static void Main() 
    { 
     ColaMachine Scherm; 
     Scherm = new ColaMachine(); 
     Application.Run(Scherm); 
    } 
} 

下一個:如果你想返回一個變量,私人,使用性能。 IC將是一種公共方法(屬性)。 InsertedCoins將是一個私有變量。

public double IC 
{ 
    get 
    { 
     return InsertedCoins; 
    } 
    set 
    { 
     InsertedCoins = value; 
    } 
} 

不要忘記,該機擁有很多狀態。你應該使用設計模式,正好狀態模式

+0

謝謝!我有很多基本的編程規則還有待學習。 – 2012-03-11 02:57:33

相關問題