WinForm 介面布局

來源:互聯網
上載者:User

http://blog.163.com/prince.king_521/blog/static/106891204201192410455319/

得剛從Web轉向WinForm開發時有一段狂喜,沒有Session丟失、沒有瀏覽器不相容,不用圍著HTML、CSS、Javascript、 C#打轉,在Visual Studio裡控制項擺成什麼樣子最後就是什麼樣子(雖然根據終端使用者的作業系統和解析度設定有稍微的不同),這種感覺好久沒有過了,但隨著開發的介面越來 越複雜卻有些無措。

接下來我會分兩篇來介紹WinForm介面布局中需要注意的一些事情,上篇介紹的是一些簡單但也常見的,而下篇會接觸更為複雜但靈活的內容。

Dock & Anchor

Dock和Anchor是水火不容的,同時給控制項設定Dock和Anchor屬性時後設定的會覆蓋前面的設定。

Dock

我初接觸WinForm的時候發現控制項的Width和Height只能是int,不能設定為百分比,那個時候就想子控制項如何跟著父控制項而變化呢?父控制項變大就變大,而且還填滿那個地區。甚至以為這個需要通過代碼來解決,如是在SizeChanged事件裡……

後來才發現我要的就是Dock給的,Dock是停靠的意思。Dock屬性的類型是DockStyle枚舉:

   1: public enum DockStyle
   2: {
   3:     None = 0,
   4:     Top = 1,
   5:     Bottom = 2,
   6:     Left = 3,
   7:     Right = 4,
   8:     Fill = 5
   9: }

預設是None,當為Left的時,就表示子控制項停靠在父控制項的左邊地區,並把左地區填充滿:

中的Panel總是會停靠在Form的左邊地區,不管如何調整Form的高度,它總是能把左邊地區填滿。Dock麻煩的地方在於多個控制項碰到一 起時,比如有兩個Panel都設定為Left該怎麼辦?我們會發現向父控制項的Controls集合中添加子控制項,越晚添加具有更高的“優先順序”(不知道有 沒有這個說法,這是我杜撰的)。這裡的優先順序指的是,子控制項“優先順序”越高,越靠近父控制項邊緣,其他子控制項就得避讓:

this.Controls.Add(this.panel1);
this.Controls.Add(this.panel2);

 

Panel2後添加進去,所以它具有更高的優先順序,更靠近Form的邊緣。這個規則不僅僅對於Dock都設為Left的有效,對Dock屬性不同,但是碰到一起的子控制項也適用:

   1: this.panel1.Dock = DockStyle.Left;
   2: this.panel2.Dock = DockStyle.Left;
   3: this.panel3.Dock = DockStyle.Top;
   4:  
   5: this.Controls.Add(this.panel1);
   6: this.Controls.Add(this.panel2);
   7: this.Controls.Add(this.panel3);

panel3的Dock設定為Top,最後添加到Controls集合中,所以具有最高的優先順序,其他兩個panel都得避讓: 

將Panel3調整成第二個添加進去呢?卻是這番景象: 

當然,這裡的“優先順序”比較只在同一個“層次”起作用,將子控制項與父控制項同一層次的控制項相比較是沒有意義的。

Anchor

Dock一般是劃分地區的,將一個表單或大控制項劃分幾個大地區以便布局,就像Web中的div一樣。但有的時候我們卻想子控制項在父控制項裡的相對位置 不要隨著父控制項的變大縮小而變化,或者控制項邊緣距離父控制項邊緣的相對距離不要發生變化,但又不是停靠在父控制項的邊緣,這就是Anchor該出場的時候了。

Anchor屬性的類型是AnchorStyles位標記(如果不理解位標記就將其理解為可以使用位元運算符進行操作,從而可以設定多個值的枚舉吧,深入理解請參見MSDN或《CLR via C#》中對位標記的描述):

   1: [Flags]
   2: public enum AnchorStyles
   3: {
   4:     None = 0,
   5:     Top = 1,
   6:     Bottom = 2,
   7:     Left = 3,
   8:     Right = 4
   9: }

Anchor的預設值是Anchor.Left | Anchor.Top,也就是子控制項與父控制項的左邊緣和上邊緣的相對位置不會變化,這也保證了在表單最大化後子控制項的位置不會發生變化:

表單預設顯示時->

表單變大後->

 

還是懸停在左上方不會發生變化。那如果設定為Left和Right呢?當Anchor設定為Left|Right的時候,為了確保父控制項(在這裡就是Form)變大時,控制項的邊緣與父控制項距離不變,子控制項會自動的擴大:

總之,記著Anchor的中文意思:錨。當給控制項設定Anchor的時候,就相當於用一個鐵釘將控制項的邊緣給釘住。

Padding & Margin

Padding和Margin沒有什麼好說的,和CSS的盒模型描述的一模一樣,Padding指的是控制項內部空間,Margin指的是控制項之外的:

padding和margin都可以指定四個值。

AutoSize

有的時候我們需要控制項隨著裡面的內容的增長而增長,比如在做多語言的程式時,各國的語言描述同一個意思的時候長度會不同,這個時候就需要AutoSize為true了,這樣當文字過長不會被截斷。關於AutoSize更詳細的內容請參見MSDN。

如何面對複雜介面?出了問題咋辦?設計時

當介面變得越來越複雜的時候,我們很期望瞭解控制項之間的層次關係,這個按鈕是放在哪個Panel上?這個Panel的地區又是咋樣的。我剛接觸 WinForm的時候,我非常期望WinForm上也有類似於IE Developer Toolbar的工具,點擊HTML,可以可視化的在介面上顯示地區,在介面上選中某地區,也可以定位到HTML元素。實際上在設計WinForm介面時 也是可以的。這就是Visual Studio的Document Outline視窗(View->Other Windows->Document
Outline):

不過如果你只想順著button1->panel4->panel3->……這條線導航控制項樹,有更方便的方法:ESC鍵。選中一個控制項,然後敲ESC鍵就會順著這個控制項層次不斷的上溯。

選中一個控制項,然後點擊右鍵,還會出現 Select …的菜單,可以選中該控制項的某個父控制項:

真是夠方便的~~~

運行時

不過有個問題是,上面的方法都是設計時的,有的時候我們的程式中如果動態修改了某些涉及布局的屬性最後發現介面亂套了,這可咋整。運行時的問題當 然要運行時解決,給某個父控制項附加Layout事件,當修改了涉及Layout的屬性時會觸發這個事件(也有特例,下一節介紹)。這個事件會有一個 LayoutEventArgs參數,該參數有AffectedProperty屬性,該屬性指示的就是影響布局的罪魁禍首,你就找到病症所在了。

SuspendLayout & ResumeLayout

我想大家對這兩個方法肯定不預設,幾乎在WinForm裡的InitializeComponent方法裡,在方法開始處有會調用 SuspendLayout方法,然後在方法快結束處會調用ResumeLayout方法。有些的讀者也許還嘗試過刪除這兩個方法,發現程式表現行為和以 前也一樣。

瞭解這兩個方法對WinForm程式的效能還是挺有協助的,在上一節提到修改涉及Layout的屬性時會觸發Layout事件,但是有特例,特例就 是調用了SuspendLayout方法,關於修改哪些屬性會觸發Layout事件請查閱MSDN。在代碼中如果修改Size、Dock等屬性或向父控制項 添加子控制項時,會執行布局邏輯,有的時候甚至會重繪。當我們要修改一堆的這樣的屬性時,比如前面提到的InitializeComponent方法,我們 當然不想修改一下就執行一次布局邏輯,那太慢了。這個時候在修改之前你就可以調用SuspendLayout方法掛起布局邏輯,等所有屬性都設定好後再調
用ResumeLayout屬性,特別是在介面很複雜的時候效能有很大的提升。

Visual Studio預設將設定這些屬性的語句全部放在InitializeComponent方法裡,然後用SuspendLayout和 ResumeLayout括住,所以我們一般不要自作主張的將這些屬性移出到外面設定,不過有的時候我們想在代碼裡動態產生一些介面,比如添加一些子控制項 什麼的,我們最好也像VS乾的那樣調用這兩個方法。

要注意的是,並不是調用了Form的SuspendLayout和ResumeLayout方法就一了百了了。如果你是向一個Panel添加子控制項,你還得調用Panel的這兩個方法。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.