1. 程式人生 > >Java進擊C#——應用開發之WinForm開發

Java進擊C#——應用開發之WinForm開發

logs i++ mex 有時 數據 rst 流動 應用程序 dir

本章簡言

上一章筆者介紹了關於WinForm環境。這一章筆者將繼續講WinForm。只不過更加的面向開發了。事實就是在學習工具箱裏面的控件。對於WinForm開發來講,企業對他的要求並沒有那麽高。但是如果是遊戲相關的話,不好意思!筆者覺得你可能選錯語言了。C++可能更合適你。有一點希望讀者們明白。下列講到的內容是筆者在開發用的。只能輔助你學習,卻不能成為教材。上一章講到WinForm開發就是JAVA的Awt和Swing編程。筆者在做Awt和Swing已經過去四年多了。如果記得沒有錯的話,在設計窗體的時候筆者常常會用到關於FlowLayout類,BorderLayout類,JPanel類等布局類。所以先讓我們看一下關於WinForm的布局吧。

WinForm布局

說到布局,筆者只能先從屬性窗體切入了。記得大部分的控件都是從Control類這裏繼承過來的。而Control類中有倆個屬性跟布局有一定有關系。一個是Anchor屬性,一個是Dock屬性。

Anchor屬性的作用就是把控件綁定到其容器的邊緣並確定控件隨其容器一起調整大小。但是是按什麽樣的比列調整筆者也不是很清楚。MSDN也沒有找到相關的說法。只是說明控件隨其容器一起調整大小。下面就是Anchor屬性的值。

技術分享
    public enum AnchorStyles
    {
        // 摘要: 
        //     該控件未錨定到其容器的任何邊緣。
        None = 0,
        //
        // 摘要: 
        //     該控件錨定到其容器的上邊緣。
        Top = 1,
        //
        // 摘要: 
        //     該控件錨定到其容器的下邊緣。
        Bottom = 2,
        //
        // 摘要: 
        //     該控件錨定到其容器的左邊緣。
        Left = 4,
        //
        // 摘要: 
        //     該控件錨定到其容器的右邊緣。
        Right = 8,
    }
技術分享

如果你設置Right的話,當你把容器往右邊拉的話,設置的控件大小也往右邊變。還是讓筆者舉一個例子吧。

技術分享

從圖上可以看出筆者設置了四個值——上下左右。現在筆者就拖動一下看看他們的變化吧。

技術分享 技術分享

按扭是放在一個Panel類的容器裏面的。現在筆者拖動了Panel就是發現按扭跟著一起發現變化。

Dock屬性這個可以說是跟JAVA的BorderLayout類是一個樣子的。把容器分為上、下、左、右、中五大區。所以對應的Dock屬性的值也有五種。

技術分享
 1     public enum DockStyle
 2     {
 3         // 摘要: 
 4         //     該控件未停靠。
 5         None = 0,
 6         //
 7         // 摘要: 
 8         //     該控件的上邊緣停靠在其包含控件的頂端。
 9         Top = 1,
10         //
11         // 摘要: 
12         //     該控件的下邊緣停靠在其包含控件的底部。
13         Bottom = 2,
14         //
15         // 摘要: 
16         //     該控件的左邊緣停靠在其包含控件的左邊緣。
17         Left = 3,
18         //
19         // 摘要: 
20         //     該控件的右邊緣停靠在其包含控件的右邊緣。
21         Right = 4,
22         //
23         // 摘要: 
24         //     控件的各個邊緣分別停靠在其包含控件的各個邊緣,並且適當調整大小。
25         Fill = 5,
26     }
技術分享

你們可以自己動手試一下。就是設置對應的值。就是可以零距離停靠所設置的區。算了。筆者設置一下TOP吧。看一下樣子吧。

技術分享

上面倆個屬性的功能大概多了解了。接下就來講一下關於FlowLayoutPanel控件吧。JAVA的FlowLayout有一點類似。意為流動布局。而C#的這個叫流式布局面板。是一個容器。看一下下面的圖片吧。

技術分享

我們可以看到,如果不夠位置放一個按扭的時候,會自動換行存放。FlowLayoutPanel控件裏面有一個叫FlowDirection屬性來設置流動的方向。是從左到右,是從上到下。這個嗎讀者們自行查看。

用戶定義控件

在開發過程中,我們會發現官方提供的控件有時候並不能滿足我們自己的業務需求。這個時候怎麽辦呢?其實開發人員完全可以自己組裝一個控件。即是用戶定義控件。選中項目右擊》添加》用戶控件。

技術分享

技術分享

填寫對應的用戶控件的名稱之後,點擊添加按扭。visual studio就會切換到用戶控件的設計窗體界面,同時項目裏面會多出一個文件。如下

技術分享

技術分享

上面的項目結構的圖片了吧。我們可以看到多出一個叫ATextBox.cs的文件。文件前面的圖標跟窗體的圖標一點也不一樣子。可是你卻會發現操作卻跟窗體操作是一樣子。沒有錯。你可以把這個界面當作對窗體的操作就可以了。相信筆者不用多說了。該拖控件就拖吧。

如果你用心的話,可以點開他。這個時候你會發現真的有一點像呢?

筆者拖一個TextBox到ATextBox.cs裏面吧。然後在拖動改變一下ATextBox.cs的大小吧。如圖下。

技術分享

好了。就這樣子吧。那麽要什麽用呢?雙擊Form1.cs窗體。這個時候我們會發現對應的工具箱裏面會出現一些細微的變化。

技術分享

看到這裏。不用筆者多說拉到對應的窗體就可以了使用了。這裏要註意一點:如果你的用戶控件發生了代碼上的修改。就必須重新生成。這個時候拉出來才有可能是最新的。為了區別筆者把ATextBox.cs的背影色改為紅色。讓我們看一下吧。

技術分享

讓我們切到後面的代碼吧。筆者在代碼裏面加了一個叫AText的屬性。如下

技術分享
 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Drawing;
 5 using System.Data;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 
10 namespace WinFormExample
11 {
12     public partial class ATextBox : UserControl
13     {
14         public ATextBox()
15         {
16             InitializeComponent();
17         }
18         public string AText
19         {
20             set { this.textBox1.Text = value; }
21             get { return this.textBox1.Text; }
22         }
23     }
24 }
技術分享

這個時候我們來看一下。對應他的屬性窗體裏面就會出現相應的屬性了。這個樣子就可以修改他的值了。

技術分享

相信讀者們能明白筆者要表達的是什麽意思了吧。沒有錯。如果你寫了相關的事件。也會在他的屬性窗體裏面出現。那麽有時候如果不想讓他出現在屬性窗體裏面怎麽辦呢?這個時候我們就要看一個類了。UserControl類就是最好的學習了。按F12相看UserControl類。我們會發現一些註解。如Browsable、EditorBrowsable等。沒有錯。這些都是用於表示對應屬性在屬性窗體的行為。筆者就不用多說了吧。

[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[EditorBrowsable(EditorBrowsableState.Always)]
public override bool AutoSize { get; set; }

關於用戶控件筆者就寫到這裏。這部分的內容筆者在開發過程中也很少用到。但是如果是大型PC端的軟件開發。那一般都會用到。請讀者們自己查閱。

應用程序配置文件

應用程序配置文件就是App.config。這是.NET自己創造一個以.config為擴展名的配置文件(事實上就是一個XML)。所以在讀取上可以不用XmlDocument類。當然你要是覺得不爽也可以用XmlDocument了。這並沒有多大影響。但是為了專業精神有時候筆者還是會用C#的讀取方式。那App.config是什麽呢?在開發WinForm一般都會用到他。你可以把對應的數據庫連接字符串放在App.config。也可以存放一些其他的信息。沒有錯。就是用於存放應用程序的配置信息。那麽C#自己提了一個叫ConfigurationManager類。這個類就是用於讀取App.config。不多說讓筆者舉例子吧。

ConfigurationManager類是在System.Configuration的dll裏面的。如果項目的引用裏面沒用的話。不好意思。請先引了一下。關於這一點相信《Java進擊C#——項目開發環境》足夠讓你了解到。然後,就可以創建一個App.config了。選項目右擊》添加》新建項。這個相信大家都明白了吧。

技術分享

在常規裏面就可以找到對應的“應用程序配置文件”了。選擇“添加”。項目裏面就會出現App.config.內容如下。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

好了。我們要做的就是在App.config裏面增加相關的信息了。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="Aomi" value="i am aomi"/>
  </appSettings>
</configuration>

這個時候筆者就要去讀取相關的信息了。筆者在窗體裏面拖了一個Label控件和一個按扭控件。點擊按扭就把配置信息的值讀取出來。賦值給Label控件。

技術分享

後面代碼

技術分享
 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 using System.Configuration;
10 
11 namespace WinFormExample
12 {
13     public partial class Form1 : Form
14     {
15         public Form1()
16         {
17             InitializeComponent();
18         }
19 
20         private void button1_Click(object sender, EventArgs e)
21         {
22             this.label1.Text = ConfigurationManager.AppSettings["Aomi"];
23         }
24     }
25 }
技術分享

看到代碼了吧。就一句很簡單的話就可以了。讓我們看一下運行的情況吧。

技術分享

關於App.config不只是筆者講的這些。還可以用於設置開發軟件的一些系統設置。這可就多了。是寫不完的。請筆者們自行查閱。

BackgroundWorker類

這個類你可以理解為後臺線程。在開發過程中,程序有很多不需用戶看到的工作。這些工作一般都可以交給後面線程去工作。而BackgroundWorker類就是最好的代表了。對於BackgroundWorker類本來筆者應該在多線程那章節一起講的。可是筆者想一下覺得放在這裏比較合適。WinForm的界面執行都是在一個叫UI線程裏面做的。那麽UI線程有一個特色就是後臺線程是訪問不了UI線程裏面的控件。一般的訪都要用到一個叫Invoke方法。他是在Control類裏面的。所以不管是控件還是窗體都有這個方法。看一下下面的代碼吧。

技術分享
 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 using System.Configuration;
10 using System.Threading;
11 
12 namespace WinFormExample
13 {
14     public partial class Form1 : Form
15     {
16         public Form1()
17         {
18             InitializeComponent();
19         }
20 
21         private void button1_Click(object sender, EventArgs e)
22         {
23             this.label1.Text = ConfigurationManager.AppSettings["Aomi"];
24         }
25 
26         private void Form1_Load(object sender, EventArgs e)
27         {
28             Thread myThread = new Thread(this.Trace);
29             myThread.Start();
30         }
31 
32         public void Trace()
33         {
34             this.Invoke(new Action(() =>
35             {
36                 this.label1.Text = "這是一個 Trace";
37             }));
38         }
39     }
40 }
技術分享

如果把它去掉的話,就會發生異常。如下

技術分享

筆者舉一個列子來說明一下BackgroundWorker類的用法吧。

技術分享
 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 using System.Configuration;
10 using System.Threading;
11 
12 namespace WinFormExample
13 {
14     public partial class Form1 : Form
15     {
16         private BackgroundWorker _backgroudWorker;
17         public Form1()
18         {
19             InitializeComponent();
20         }
21 
22         private void button1_Click(object sender, EventArgs e)
23         {
24             if (this._backgroudWorker == null)
25             {
26                 this._backgroudWorker = new BackgroundWorker();
27                 this._backgroudWorker.WorkerSupportsCancellation = true;
28                 this._backgroudWorker.WorkerReportsProgress = true;
29                 this._backgroudWorker.DoWork += BackgroudWorker_DoWork;
30                 this._backgroudWorker.ProgressChanged += BackgroudWorker_ProgressChanged;
31                 this._backgroudWorker.RunWorkerCompleted += BackgroudWorker_RunWorkerCompleted;
32             }
33 
34             this._backgroudWorker.RunWorkerAsync();
35            
36         }
37 
38         private void BackgroudWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
39         {
40             this.progressBar1.Value = e.ProgressPercentage;
41         }
42 
43         private void BackgroudWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
44         {
45             this.label1.Text = e.Result.ToString();
46         }
47 
48         private void BackgroudWorker_DoWork(object sender, DoWorkEventArgs e)
49         {
50             string value = ConfigurationManager.AppSettings["Aomi"];
51             e.Result = value;
52 
53             for (int i = 0; i < 100; i++)
54             {
55                 this._backgroudWorker.ReportProgress(i);
56                 Thread.Sleep(200);
57             }
58 
59         }
60        
61     }
62 }
技術分享

運行結果

技術分享

BackgroundWorker類把後臺和前臺分開。並且又可以在後臺執行過程中通知前臺。我們可以看到BackgroundWorker類還是很強大的。同時也可以不用Invoke方法。

WorkerSupportsCancellation屬性:用於表示是否可以在運行中取消工作。

WorkerReportsProgress屬性:用於表示是否可以在運行中通知前臺。

DoWork事件:後臺線程

ProgressChanged事件:前臺UI線程。用於後臺線程中通知的時候執行。

RunWorkerCompleted事件:前臺UI線程。用於後臺線程結束之後執行。

RunWorkerAsync方法:開始異步運行。

本章總結

本章主要是講到關於筆者在開發過程中用到的幾個知識點。也是筆者認為學習WinForm必須要懂得。關於WinForm筆者就簡單的介紹到這裏。下一章我們要去看一下關於Linq和EF的知識點。

Java進擊C#——應用開發之WinForm開發