日期: 2023.10.03 星期二
練習解答
2023.09.28,設計一個網頁可以輸入圓半徑,按下按鈕,算出圓半徑與周長,並顯示它。-
建立新專案: 檔案 > 新增 > 專案




-
產生
UI: 點選方案後,滑鼠右鍵,選擇加入Web 表單

指定項目的名稱:WebForm1即表單項目名稱

-
產生後的表單
WebForm1.aspx有兩子項目如下,雙擊WebForm1.aspx項目就可以進入設計介面。WebForm1.aspx.cs選此項,點擊滑鼠右鍵,選擇設計工具檢視,也可以進入設計介面WebForm1.aspx.designer.cs
-
使用工具箱,加入以下控制項(元件)
- 加一
TextBox1 - 加一
Button1。 - 加一
Label1,刪掉Lebel1.Text值。

- 加一
-
為按鈕產生事件的方法
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; } } - 輸出

基本類別設計
-
前因: 上面方法的設計,有一缺點,因為圓的計算寫在主程序中,假設有
n個WebForm都須計算圓面積,那這樣不是在每一個WebForm假設計算公式有修改,那不是要到每一個WebForm。 - 所以用物件導向的寫法來改善它。
- 專案下新增一個類別,滑鼠指向專案後,滑鼠右鍵 > 加入 > 類別,

取類別名稱Circle後,按下新增。

-
開始撰寫類別的屬性與方法
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; } } -
類別完成開始使用
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; } } -
執行測試,得到一樣結果,但是更容易維護。
-
修改
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; } } -
Circle類別中的屬性radius其可視性為public, 所以在任何位置都可以找到這個屬性raduis,但為了資料的安全,盡量不要讓別人看得到所定義的屬性成員或方法,如果是公開的原因,任何一個人都可以輕易地修改該值,所以通常類別 (這裡Circle) 中的屬性(radius),可視性是為不可視的private,改成private後,執行cc.raduis就會找不到該raduis,這屬性就不能讓別人輕易讀取了,需透過我指定的方式(方法) 來讀取這個屬性了,但缺點變成其他人無法修改它,如果需要就必須透過建構子輸入半徑,但是如果想讓其他使用者還是能存取它(radius) 使用別的名字取代,不要用原名,像是使用別名的概念,如何操作呢,java語言使用get、set,c#語言用存取子方式,而存取子的方式:
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{},可以自行決定要提供哪一個方法。
類別繼承
-
引言:
java繼承與c#不同,c#使用符號:表示繼承。 -
現有專案上新增一個類別
Item料件。public class Item{ //使用預設建構式 //產生若干屬性,使用標準存取子方式 public string ID{ get;set; } public string Name{ get;set; } public string Full_Name(){ return ID + "_" + Name; } } -
在現有專案上在新增一個類別
Product產品。//繼承類別 Item public class Product:Item{ //定義自己的屬性與方法 public double Price{ get;set; } //方法,計算賣了多少錢(價格*數量) public double Total_Sales(int volumn){ return volumn * Price; } } -
產生一新表單
WebForm2

加入控制項:
- 文字: ID
TextBox1輸入 ID - 文字: Name
TextBox2輸入品名 - 文字: Price
TextBox3輸入價錢 - 文字: Quantity
TextBox4輸入數量 Button1按下取顯示產品完整名稱,總共銷售多少錢Label1輸出: 產品名稱,刪除值Label2輸出: 總銷售金額,刪除值

- 文字: ID
-
按下 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(); } - 執行畫面輸出

抽象類別
- 前言:
abstract class,C#與Java相同,抽象類別不同於一般類別,不可產生實體物件,所以不會有建構子,可以定義屬性與方法。 - 定義抽象類別: 任何一
Shape(形狀)是可以計算面積與周長,但是不能指定其面積與周長要如何計算,因為並沒指定是甚麼形狀,形狀是一個抽象的名詞,可以把它視為抽象類別,反之,如三角形可以說是一般物件,可以知道如何來計算面積與周長,是可以產生一實體物件的。 - 抽象類別使用時機
定義抽象類別,一般都是給繼承使用,所以意指其它類別要去繼承Shape,但是如果要繼承這抽象類別,就必須實作所有其中的抽象方法。 -
實作
加入一新類別:Shape於專案後public abstract class Shape { //定義方法 public string Developer() { //如果是一般方法可以實作,抽象類別中,方法可以實作 return "ABC"; } //如果定義的是抽象方法就不可以實作它 public abstract double Area(); public abstract string ShapeType(); } -
在加入一新一般類別:
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; } } -
專案下新增一
WebForm3來作應用

-
介面
- 文字: 底
TextBox1 - 文字: 高
TextBox2 Button: 產生面積(底 * 高) /2Label: 輸出結果,刪除預設值。

- 文字: 底
-
按下
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(); } - 執行結果

-
介面
-
前言
Interface,C#與Java的定義基本上相同,介面可以定義屬性與方法,但通常屬性用來定義某一個特定的定值,它主要定義一個方法。
介面與抽象類別的不同,介面是給大家看,它提供那些功能、方法可以使用,但是介面中定義的方法全部不可以實作,但抽象類別是可以實作的(指其中的一般方法)。Interface是給別人使用的,預設是公開的,所以不會在寫上可視性(public、private、protected)。- 介面需使用一般類別來實作介面定義的所有方法,在
Java語言使用關鍵字implement,但在C#中跟繼承相同都是使用:符號。
-
案例:
-
先產生一介面: 第一次使用,需到加入 > 新增項目,

然後在Visual C#`` 項目下選擇**介面**,給任一名稱,這裡A.cs`

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


-
編輯
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"; } } -
討論
若使用一新表單,裡面有一按鈕要來使用這介面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 有二個為一值的屬性(Name、Gender)、和一個多值的屬性 Skills 與一個方法 get_info(),能判斷性別是男生,顯示 Mr. + Name,是女生顯示 Miss + Name,並列出所有 Skills
日期: 2023.10.05 星期四
Visual Studio 2022 的 Web Form 設計新介面問題
Visual Studio 2022 更新後,推出 Web Live Previewer 功能,像要取代現在 WebForm 設計介面的方式,但是有問題,所以暫時不要用,如何修改
提示
工具 > 選項 > 環境 的 Web Form 設計工具

選擇 舊版 Web Form 設計工具

選擇後按下確定,重新啟動 Visual Studio 就會看到舊的 WebForm 設計介面。
練習解答
- 問題: 參考
2023.10.03。 -
建立新專案: 檔案 > 新增 > 專案




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


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; } } -
設計好該類別,就可以開始使用它,接著產生
Web 表單,

-
設計一
UI,能輸入員工姓名,選擇性別,然後選擇他會有那些技能,在按下一個按鈕就可將這些員工細節資料印出。- 文字:
NameTextBox1 - Gender 使用
RadioButton* 2RadioButton1.Text= "Male"RadioButton2.Text= "Female"
- Skills 使用
CheckBox* 3CheckBox1.Text= "Java"CheckBox2.Text= "C#"CheckBox3.Text= "C++"
Button1.Text= "Show"Label1.Text= ""

- 文字:
-
啟動程序後,發現
RadioButton在點選過後,就一直被選到,無法在改變狀態

原因是RadioButton是單選(很多選項中只能選一個),CheckBox是多選,可以在其中選取多個或是取消做選取,單選中所有選項有相關性,所以把它們視為群組,所以這些有相關的單選項中的屬性取成同一GroupName
=genter.RadioButton1.GroupName=genderRadioButton2.GroupName=gender
-
重新再啟動程序,測試介面是否正常

- 單選項目中設定一個預設被選。
RadioButton1.checked=True -
雙擊
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(); } -
測試輸出

-
實際應用情境下
RadioButton與CheckBox已經很少再使用,取而代之的是RadioButtonList,CheckBoxList這兩個是一個容器。- 刪除介面中的
RadioButton1與RadioButton2後,在工具箱中加入ButtonList1,選擇編輯項目

於ListItem集合編輯器的成員欄位,按下加入按鈕來增加項目成員ListItem,每一個ListItem都有自己的屬性,修改其屬性0 ListItem Text="Male" Value="M" Selected=true

1 ListItem Text="Female" Value="F" Selected=false

選項可橫放:RadioButtonList1.RepeatFirection=Horizontal
- 刪除介面中的
CheckBox1與CheckBox2與CheckBox3後,在工具箱中加入CheckBoxList,選擇編輯項目進行編輯,方法與上面相同



-
修改
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(); }
- 刪除介面中的
留言