WPF之路——WPF布局系統
前言
?????前段時間忙了一陣子Google Earth,這周又忙了一陣子架構師論文開題報告,現在終于有時間繼續<WPF之路>了。先回憶一下上篇的內容,在《從HelloWorld到WPF World》中,我們對WPF有了個大概的了解,并了解了初學WPF時應該從哪些知識點入手。今天我們就從最基本的知識點之一布局系統來繼續學習WPF,主要包括如下內容。
-
0,什么是布局
-
1,基本元素——面板
-
2,常用容器控件
-
3,測量與排列
-
4,基本屬性:Alignment,Margin和Pading
-
5,附加屬性
-
6,布局與性能
-
7,總結
這是一個很簡單的問題。簡單來說,就是把一些控件有條理的擺放在界面上合適的位置,顯然擺的亂七八糟不能算布局。在WPF中,這個條理與WinForm中略有不同,讓我們看個很簡單的界面:
這樣子的界面大家在熟悉不過了。依圖所示,WPF先用藍線(假設的線)將界面劃分為上下兩部分,然后再有紅線劃分出多個方格,最后放入控件,其中每部分中的控件或劃分的空格只能縱向排列,或橫向排列,不能有其他選擇。大多數情況下,WPF程序界面上的控件都要按照此種遞歸的方法逐個排列,最終形成所看到的界面。
?
在上節中我們了解了WPF布局原理,這可以簡單理解為大控件中按排或列放入小控件,小控件在按照同樣規則放入更小控件。這種能放入其他控件的控件是WPF布局系統中的基本元素——面板。面板是用來放東西的,既包括控件元素,也包括面板自己。面板不僅能承載其他子元素(控件),還能控制子元素的大小,位置以及如何排列。例如上述例子中,藍線劃分的面板控制子元素只能上下排列,而紅線劃分的面板控制的子元素只能橫向排列。
?????WPF默認提供了幾種面板都是從基面板(Panel)繼承而來,看一下它們的繼承鏈。
?????System.Windows.Threading.DispatcherObject
??????? System.Windows.DependencyObject
????????? System.Windows.Media.Visual
??????????? System.Windows.UIElement
????????????? System.Windows.FrameworkElement??????????????? System.Windows.Controls.Control
??????????????? System.Windows.Controls.Panel
????????????????? System.Windows.Controls.Canvas
????????????????? System.Windows.Controls.DockPanel
????????????????? System.Windows.Controls.Grid
????????????????? System.Windows.Controls.StackPanel
????????????????? System.Windows.Controls.VirtualizingPanel
????????????????? System.Windows.Controls.WrapPanel
?
WPF默認提供了數種布局控件,常用的包括如下幾種:?
名稱 用法 說明 Canvas 此面板可承載任意元素,包括控件,圖形,甚至文字。各種元素依據屏幕坐標確定位置。 DockPanel 此面板可指定元素的排列停靠方式,每個子元素的排列方式可以不同。 Grid 此面板使子元素按照縱橫網格排列。 StackPanel 此面板使子元素按照水平或垂直方向排列,兩個方向只能選其一。 VirtualizingStackPanel
與StackPanel相同,不同之處在于它可以使內容虛擬化。 WrapPanel 使子元素按照水平或垂直方向排列,在行或列處換行或列,依舊按照水平或垂直方向從左到右或從上到下排列。 3,測量與排列
當我們在面板上放入子元素,并設置相應的屬性時,WPF的布局系統自動為我們完成2個過程:測量和排列,這是兩個非常重要的過程。
由于WPF界面元素有很多與布局有關的屬性,如坐標,大小,對齊方式,相對位置,間距等。首先這些屬性使用的是與設備無關的分辨率單元,這導致同樣大小的元素在不同界面上顯示的效果可能不同;其次每個屬性值有一定的優先級,例如Button的Height和Width屬性優先于Stretch屬性,如果設置 Height, Width 以及 Stretch,會導致 Stretch被忽略。
因此,盡管在設計時指定了屬性值,布局系統依然需要重新計算每個子元素在界面上的實際大小,位置,邊距等值,這些值被稱為“FinalSize”。
?
4,基本屬性:Alignment,Margin和Pading
在設計UI時,WPF為我們提供了一些屬性用于精確定位元素,其中最常用的有三個:Alignment(包括水平,垂直),Margin,Pading,具體用法如下:
名稱 說明 Alignment 子元素在水平(垂直)方向的對齊方式,有左對齊,右對齊(頂端對齊,底部對齊),中間對齊,拉伸填充等四種方式。 Margin 用于指定元素與其子級或同級之間的距離,包括上下左右四個值。也可通過使用 Margin="20" 同時指定四個值。 Pading Padding 在大多數方面類似于 Margin,只有少數元素有(公開),用于將子元素的有效大小增大指定的厚度。
?
通過上面我們了解到子元素通過一些屬性值的設置實現在面板上布局,比如Alignment對齊屬性,Dock停靠排列屬性。這些屬性不屬于子元素本身,而依賴與所在的父元素。比如同樣是Button,在DockPanel中有Dock屬性,而在Grid中就沒有。這些屬性的存在依賴與父元素,在WPF中稱做“附加屬性”。
附加屬性的用途是允許不同的子元素為實際在父元素中定義的屬性指定唯一值,目的是讓子元素通知父元素它將如何在界面中呈現。如上面提到的DockPanel.Dock 屬性,因為它將在 DockPanel 中包含的元素上設置,而不是在 DockPanel 本身設置。注意,相對于子元素,父元素提供的附加屬性相當于全局屬性。
?
通過上面我們了解到,當給界面元素的布局屬性賦值時,布局系統需要重新計算和排列所有子元素的“FinalSize”(因為改變影響不可知)。這是一個遞歸的過程。如果不注意,可能會帶來性能問題。因此在設計時應注意下面幾點:
1,應注意哪些屬性值更改會引起執行布局系統的遞歸更新;
2,如有可能,應使用 RenderTransform 而不要使用 LayoutTransform;
3,避免不必要地調用 UpdateLayout,因為UpdateLayout強制調用布局系統的遞歸更新;
4,當包含大量元素集合時,請使用 VirtualizingStackPanel虛擬化元素;
?
通過本文,我們大概了解了WPF的布局系統,常用的布局面板,與布局有關的幾個屬性,以及設計開發UI時的注意事項。這些內容很多與WinForm中的相關概念相通,可以說是舊瓶裝新酒,稍加思考,并不難理解;如果深入了解,會發現與WinForm截然不同。但作為初學者,如果能靈活使用文中所講的知識點,深入理解注意點,對自身的提高還是很有幫助的