日期: 2023.10.03 星期二

練習解答

  1. 2023.09.28,設計一個網頁可以輸入圓半徑,按下按鈕,算出圓半徑與周長,並顯示它。
  2. 建立新專案: 檔案 > 新增 > 專案
    20231031072102
    20231031072236
    20231105172637
    20231031150345

  3. 產生 UI: 點選方案後,滑鼠右鍵,選擇加入 Web 表單
    20231103143257
    指定項目的名稱: WebForm1表單項目名稱
    20231031074051

  4. 產生後的表單 WebForm1.aspx 有兩子項目如下,雙擊 WebForm1.aspx 項目就可以進入設計介面。

    • WebForm1.aspx.cs 選此項,點擊滑鼠右鍵,選擇設計工具檢視,也可以進入設計介面
    • WebForm1.aspx.designer.cs
  5. 使用工具箱,加入以下控制項(元件)

    • 加一 TextBox1
    • 加一 Button1
    • 加一 Label1,刪掉 Lebel1.Text 值。
      20231105174255
  6. 按鈕產生事件的方法

    protected void Button1_Click(object sender, EventArgs e)
    {
        try
        {
            //輸入資料轉換成資料型態浮點
            double r = Double.Parse(TextBox1.Text);
            //計算圓面積 pi * r *r
            double area = Math.PI * Math.Pow(r, 2);
            //浮點資料轉成字串
            Label1.Text = area.ToString();
        }
        catch (Exception err)
        {
          Label1.Text = err.Message;
        }
    }
  7. 輸出
    20231105220925

基本類別設計

  1. 前因: 上面方法的設計,有一缺點,因為圓的計算寫在主程序中,假設有 nWebForm 都須計算圓面積,那這樣不是在每一個 WebForm 假設計算公式有修改,那不是要到每一個 WebForm

  2. 所以用物件導向的寫法來改善它。
  3. 專案下新增一個類別,滑鼠指向專案後,滑鼠右鍵 > 加入 > 類別,
    20231105222532
    取類別名稱 Circle 後,按下新增
    20231105223041
  4. 開始撰寫類別的屬性與方法

    public class Circle
    {
        //定義一屬性半徑
        public double radius;
        //定義建構子才能產生物件
        //公開的、不須回傳值
        public Circle()
        {
        }
        //定義有參數的建構子
        public Circle(double r)
        {
           //設定 radius = r
           radius = r;
        }
        //計算面積的方法
        public double Area()
        {
            return Math.PI * Math.Pow(radius, 2);
        }
        //計算周長的方法
        public double Circumference()
        {
            return 2 * Math.PI * radius;
        }
    }
  5. 類別完成開始使用

    protected void Button1_Click(object sender, EventArgs e)
    {
       try
       {
           Circle cc = new Circle();
           cc.radius = Double.Parse( TextBox1.Text);
           Label1.Text = cc.Area().ToString();
       }
       catch (Exception err)
       {
          Label1.Text = err.Message;
       }
    }
  6. 執行測試,得到一樣結果,但是更容易維護。

  7. 修改 Button1_Click() 方法,建立物件時,改使用 Circle 類別的帶有一參數建構式,

    protected void Button1_Click(object sender, EventArgs e)
    {
        try
        {
            Circle cc = new Circle(double.Parse(TextBox1.Text));
            Label1.Text = cc.Area().ToString();
        }
        catch (Exception err)
        {
            Label1.Text = err.Message;
        }
    }
  8. Circle 類別中的屬性 radius 其可視性為 public, 所以在任何位置都可以找到這個屬性 raduis,但為了資料的安全,盡量不要讓別人看得到所定義的屬性成員或方法,如果是公開的原因,任何一個人都可以輕易地修改該值,所以通常類別 (這裡 Circle) 中的屬性(radius),可視性是為不可視的 private,改成 private 後,執行 cc.raduis 就會找不到該 raduis,這屬性就不能讓別人輕易讀取了,需透過我指定的方式(方法) 來讀取這個屬性了,但缺點變成其他人無法修改它,如果需要就必須透過建構子輸入半徑,但是如果想讓其他使用者還是能存取它(radius) 使用別的名字取代,不要用原名,像是使用別名的概念,如何操作呢, java 語言使用 getsetc# 語言用 存取子 方式,而存取子的方式:
    public double Radius{}

    存取子須公開因要讓別人找的到,資料型態與原 private double radius 的型態相同,名字可取任一名稱,這裡為 Radius,跟建構式相同需有一對大括號,大刮號內有兩方法 get{} 取值、set{} 設定值。

    public double Radius{
      //get 方法,不用 (),回傳 radius 值
      get{
       return radius;
      }
    
      //設定值,C# 中使用者輸入的值用 value 代表。
      set{
        radius = value;
      }
    }

    使用

    protected void Button1_Click(object sender, EventArgs e)
    {
        try
        {
            Circle cc = new Circle(double.Parse(TextBox1.Text));
            //去值時執行 get 方法
            double k = cc.Radius;
            //設定值時
            //該屬性是存取子,顯示符號為板手, 6 為 value 的值
            cc.Radius = 6;
            Label1.Text = cc.Area().ToString();
        }
        catch (Exception err)
        {
            Label1.Text = err.Message;
        }
    }

    但是實務上存取子寫法上只表示成一對 get;set;,所以類別 Circule 將改寫成:

    public class Circle
    {
      //拿掉 private 屬性半徑 radius
      //private double radius;
      //定義建構子才能產生物件
      //公開的、不須回傳值
      public Circle()
      {
      }
    
      //保留存取子,但寫法精簡成 set;get;
      public double Radius{
        //標準 get; 與 set; 寫法
        get;set;
        //get 方法,不用 (),回傳 radius 值
        //get{
          //return radius;
        //}
    
        //設定值,C# 中使用者輸入的值用 value 代表。
        //set{
          //radius = value;
        //}
      }
    
      //定義有參數的建構子
      public Circle(double r)
      {
        //設定 radius = r
        //radius 被拿掉了改成 Radius
        //radius = r;
        Radius = r;
      }
      //計算面積的方法
      public double Area()
      {
        return Math.PI * Math.Pow(radius, 2);
      }
      //計算周長的方法
      public double Circumference()
      {
        //return 2 * Math.PI * radius;
        return 2 * Math.PI * Radius;
      }
    }

    使用標準的 public double Radius{get; set;} 存取子 寫法,系統將自動產生一個 private 的變數名稱,並且會含有標準的方法 get{}, set{},可以自行決定要提供哪一個方法。

類別繼承

  1. 引言:

    java 繼承與 c# 不同,c# 使用符號 : 表示繼承。

  2. 現有專案上新增一個類別 Item 料件。

    public class Item{
      //使用預設建構式
      //產生若干屬性,使用標準存取子方式
      public string ID{
        get;set;
      }
      public string Name{
        get;set;
      }
      public string Full_Name(){
        return ID + "_" + Name;
      }
    }
  3. 在現有專案上在新增一個類別 Product 產品。

    //繼承類別 Item
    public class Product:Item{
      //定義自己的屬性與方法
      public double Price{
        get;set;
      }
      //方法,計算賣了多少錢(價格*數量)
      public double Total_Sales(int volumn){
        return volumn * Price;
      }
    }
  4. 產生一新表單 WebForm2
    20231107185606

    加入控制項:

    • 文字: ID TextBox1 輸入 ID
    • 文字: Name TextBox2 輸入品名
    • 文字: Price TextBox3 輸入價錢
    • 文字: Quantity TextBox4 輸入數量
    • Button1 按下取顯示產品完整名稱,總共銷售多少錢
    • Label1 輸出: 產品名稱,刪除值
    • Label2 輸出: 總銷售金額,刪除值
      20231107190002
  5. 按下 Button執行事件的方法

    protected void Button1_Click(object sender, EventArgs e)
    {
      //完全使用物件導向的方法設計
      //產生一 Product 的物件,利用建構子
      // pp 物件繼承了 Item 所以可以有其屬性與方法
      Product pp = new Product();
      pp.ID = TextBox1.Text;
      pp.Name = TextBox2.Text;
      Label1.Text = pp.Full_Name();
      pp.Price = Double.Parse(TextBox3.Text);
      Label2.Text = pp.Total_Sales(Int32.Parse(TextBox4.Text)).ToString();
    }
  6. 執行畫面輸出
    20231107191138

抽象類別

  1. 前言: abstract classC#Java 相同,抽象類別不同於一般類別,不可產生實體物件,所以不會有建構子,可以定義屬性與方法。
  2. 定義抽象類別: 任何一 Shape (形狀)是可以計算面積與周長,但是不能指定其面積與周長要如何計算,因為並沒指定是甚麼形狀,形狀是一個抽象的名詞,可以把它視為抽象類別,反之,如三角形可以說是一般物件,可以知道如何來計算面積與周長,是可以產生一實體物件的。
  3. 抽象類別使用時機
    定義抽象類別,一般都是給繼承使用,所以意指其它類別要去繼承 Shape,但是如果要繼承這抽象類別,就必須實作所有其中的抽象方法。
  4. 實作
    加入一新類別: Shape 於專案後

    public abstract class Shape
    {
        //定義方法
        public string Developer()
        {   //如果是一般方法可以實作,抽象類別中,方法可以實作
            return "ABC";
        }
        //如果定義的是抽象方法就不可以實作它
        public abstract double Area();
        public abstract string ShapeType();
    }
  5. 在加入一新一般類別: Triangle 於專案後

    public class Triangle : Shape
    {
      //建立存取子屬性 Base, Height
      public double Base { get; set; }
      public double Height { get; set; }
    
      //public string ShapeType()
      //{
          //return "Triangle";
      //}
      //上面寫法會出現綠色蚯蚓符號,指示必須加上 override 或 new 關鍵字等等,因為 Shape 抽象類別中有定義 ShapeType() 方法,而在 Triangle 中又重複定義 ShapeType() 這方法所以必須宣告要做覆寫動作 override。
      public override string ShapeType()
      {
          return "Triangle";
      }
      public override double Area()
      {
          return (Base * Height) /2;
      }
    }
  6. 專案下新增一 WebForm3 來作應用
    20231107204459

    • 介面

      • 文字: 底 TextBox1
      • 文字: 高 TextBox2
      • Button: 產生面積 (底 * 高) /2
      • Label: 輸出結果,刪除預設值。
        20231107204621
    • 按下 Button 產生事件方法

      protected void Button1_Click(object sender, EventArgs e)
      {
        //不可以產生實體抽象物件
        //xx Shape ss = new Shape();
        //產生 Triangle 物件,Triangle 類別會去繼承 Shape 抽象類別
        Triangle tt = new Triangle();
      
        //繼承後的所有屬性與方法都可以用。
        tt.Base = Double.Parse(TextBox1.Text);
        tt.Height = Double.Parse(TextBox2.Text);
        Label1.Text = tt.Area().ToString();
      }
    • 執行結果
      20231107205450

介面

  1. 前言

    • InterfaceC#Java 的定義基本上相同,介面可以定義屬性方法,但通常屬性用來定義某一個特定的定值,它主要定義一個方法
      介面與抽象類別的不同,介面是給大家看,它提供那些功能、方法可以使用,但是介面中定義的方法全部不可以實作,但抽象類別是可以實作的(指其中的一般方法)。
    • Interface 是給別人使用的,預設是公開的,所以不會在寫上可視性(publicprivateprotected)。
    • 介面需使用一般類別來實作介面定義的所有方法,在 Java 語言使用關鍵字 implement,但在 C# 中跟繼承相同都是使用 : 符號。
  2. 案例:

    1. 先產生一介面: 第一次使用,需到加入 > 新增項目
      20231107215647
      然後在 Visual C#`` 項目下選擇**介面**,給任一名稱,這裡A.cs`
      20231107220357

      編輯 A.cs 如下內容

      interface A
      {
        // 在介面裡面只會宣告(定義)方法其結構,不會給實作
        string X();
        string Y();
      }
    2. 在設計一一般類別 B.cs 來繼承介面 A.cs
      現有專案上新增一個類別 B.cs
      20231107221756
      20231107221900

    3. 編輯 B.cs 如下

      //一般 B 類別要來實作 A 介面
      public class B : A
      {
         //實作,並沒有繼承 A, 所以不用 override 這關鍵字
         public string X()
         {
            return "x";
         }
         //實作
         public string Y()
         {
            return "y";
         }
         //定義自己的方法
         public string Z()
         {
            return "z";
         }
      }
    4. 討論
      若使用一新表單,裡面有一按鈕要來使用這介面

      protected void Button1_Click(object sender, EventArgs e)
      {
        /* 不可能為 A 介面產生一個實體物件出來
           錯誤 例: A aa = new A();  因為 A 是一個介面
           正確 例: A aa = new B();
           可以 aa 資料類型 A 介面,B 為一般類別且有建構式
           只要有實作 A 的介面,都可以產生這實作 A 介面的物件 (使用一般類別 new B())
           aa 的資料類型屬於 A 介面,對使用者來說,只看到 A
           A aa = new B();  這種寫法只能
           aa.A  aa.B      aa 只能看到 A 介面的 X()與 Y() 方法,不能看到 Z() 方法,因為 aa 資料類型是 A,所以只能看到 A 介面所定義的方法 X() 與  Y(),
           如果改成 B aa = new B(); 則 aa 就可以找到  X()、Y()、Z()
       */
      }

練習

設計一個類別 Employee 有二個為一值的屬性(NameGender)、和一個多值的屬性 Skills 與一個方法 get_info(),能判斷性別是男生,顯示 Mr. + Name,是女生顯示 Miss + Name,並列出所有 Skills

日期: 2023.10.05 星期四

Visual Studio 2022Web Form 設計新介面問題

Visual Studio 2022 更新後,推出 Web Live Previewer 功能,像要取代現在 WebForm 設計介面的方式,但是有問題,所以暫時不要用,如何修改

提示
工具 > 選項 > 環境 的 Web Form 設計工具
20231108062351
選擇 舊版 Web Form 設計工具
20231108064655
選擇後按下確定,重新啟動 Visual Studio 就會看到舊的 WebForm 設計介面。

練習解答

  1. 問題: 參考 2023.10.03
  2. 建立新專案: 檔案 > 新增 > 專案
    20231031072102
    20231031072236
    20231108070554
    20231031150345

  3. 試著思考都以物件導向方式來設計程式,所有東西先把類別建立起來,對 MVC 來說這些類別就是 Model
  4. 系統分析的類別圖就是把系統某功能所需要的類別定義出來與定義類別彼此的關係。
  5. 定義一個員工 Employee 類別,完成相關屬性與方法的定義。
    20231108074858
    20231108074954

    public class Employee
    {
      //屬性: 姓名、性別,使用存取子屬性(讓它自動產生私有屬性)
      public string Name { get; set; }
      public bool Gender { get; set; }
      //技能也可以是一個類別,因它會有資料(技能代號、技能名稱、技能縮名..et),這裡用很簡單的文字方式來表示,但一個人會有很多技能
      //List<T> 是一個集合,動態的陣列,使用存取子
      public List<string> Skills { set; get; }
    
      //取得資料
      public string get_info()
      {
        string r = "";
        if (this.Gender == true)
        {
          r += "Mr. " + this.Name + "<br>";
        }
        else
        {
          r += "Miss " + this.Name + "<br>";
        }
    
        foreach(string s in this.Skills)
        {
          r += s + "<br>";
        }
    
        return r;
      }
    }
  6. 設計好該類別,就可以開始使用它,接著產生 Web 表單
    20231108074627

  7. 設計一 UI,能輸入員工姓名,選擇性別,然後選擇他會有那些技能,在按下一個按鈕就可將這些員工細節資料印出。

    • 文字: Name TextBox1
    • Gender 使用 RadioButton * 2
      • RadioButton1.Text = "Male"
      • RadioButton2.Text = "Female"
    • Skills 使用 CheckBox * 3
      • CheckBox1.Text = "Java"
      • CheckBox2.Text = "C#"
      • CheckBox3.Text = "C++"
    • Button1.Text = "Show"
    • Label1.Text = ""
      20231108205415
  8. 啟動程序後,發現 RadioButton 在點選過後,就一直被選到,無法在改變狀態
    20231108210903
    原因是 RadioButton 是單選(很多選項中只能選一個),CheckBox 是多選,可以在其中選取多個或是取消做選取,單選中所有選項有相關性,所以把它們視為群組,所以這些有相關的單選項中的屬性取成同一 GroupName
    = genter.

    • RadioButton1.GroupName = gender
    • RadioButton2.GroupName = gender
  9. 重新再啟動程序,測試介面是否正常
    20231108214152

  10. 單選項目中設定一個預設被選。
    RadioButton1.checked = True
  11. 雙擊 Button 來產生事件方法

    protected void Button1_Click(object sender, EventArgs e)
    {
        //宣告一 Employee 物件
        Employee emp = new Employee();
     List<string> ss = new List<string>();
     emp.Name = TextBox1.Text;
        if (RadioButton1.Checked)
        {
            emp.Gender = true;
        }
        else
        {
            emp.Gender = false;
        }
        if (CheckBox1.Checked)
        {
            ss.Add(CheckBox1.Text);
        }
        if (CheckBox2.Checked)
        {
            ss.Add(CheckBox2.Text);
        }
        if (CheckBox3.Checked)
        {
            ss.Add(CheckBox3.Text);
        }
     emp.Skills = ss;
        Label1.Text = emp.get_info();
    }
  12. 測試輸出
    20231108220211

  13. 實際應用情境下 RadioButtonCheckBox 已經很少再使用,取而代之的是 RadioButtonListCheckBoxList 這兩個是一個容器。

    1. 刪除介面中的 RadioButton1RadioButton2 後,在工具箱中加入 ButtonList1,選擇編輯項目
      20231108221032
      ListItem 集合編輯器的成員欄位,按下加入按鈕來增加項目成員 ListItem,每一個 ListItem 都有自己的屬性,修改其屬性

      • 0 ListItem Text="Male" Value="M" Selected=true
        20231108221711
      • 1 ListItem Text="Female" Value="F" Selected=false
        20231108221857
        選項可橫放: RadioButtonList1.RepeatFirection = Horizontal
    2. 刪除介面中的 CheckBox1CheckBox2CheckBox3 後,在工具箱中加入 CheckBoxList,選擇編輯項目進行編輯,方法與上面相同
      20231108222828
      20231108222852
      20231108222918
    3. 修改 Button1_Click 方法

      protected void Button1_Click(object sender, EventArgs e)
      {
           //宣告一 Employee 物件
           Employee emp = new Employee();
      
           List<string> ss = new List<string>();
      
           emp.Name = TextBox1.Text;
           if (RadioButtonList1.SelectedValue == "M")
           {
               emp.Gender = true;
           }
           else
           {
               emp.Gender = false;
           }
      
           for (int i = 0; i < 3; i++)
           {
               if (CheckBoxList1.Items[i].Selected)
               {
                   ss.Add(CheckBoxList1.Items[i].Text);
               }
           }
      
           emp.Skills = ss;
           Label1.Text = emp.get_info();
      }
最後修改日期: 2023 年 11 月 22 日

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。