【转】WPF入门教程系列六——布局介绍与Canvas(一)
?????? 從這篇文章開始,我們將對WPF中的界面如何布局做一個較簡單的介紹,大家都知道:UI是做好一個軟件很重要的因素,如果沒有一個漂亮的UI,功能做的再好也無法吸引用戶使用,而且沒有漂亮的界面,那么普通用戶會感覺這個軟件沒有多少使用價值。
一.?總體介紹
? ? ? ? WPF的布局控件都在System.Windows.Controls.Panel這個基類下面,使用?WPF提供的各種控件在WPF應(yīng)用程序中界面進(jìn)行布局,同時對各種子控件(如按鈕、文本框,下拉框等)進(jìn)行排列組合。
?
Pane類的公共屬性太多了。就簡單介紹幾個常見的屬性如下表。
| ?? | 名稱 | 說明 |
| ? | Cursor | 獲取或設(shè)置在鼠標(biāo)指針位于此元素上時顯示的光標(biāo)。? |
| ? | DataContext | 獲取或設(shè)置元素參與數(shù)據(jù)綁定時的數(shù)據(jù)上下文。? |
| ? | Dispatcher | 獲取與此?DispatcherObject?關(guān)聯(lián)的?Dispatcher。? |
| ? | FontFamily | 獲取或設(shè)置控件的字體系列。? |
| ? | FontSize | 獲取或設(shè)置字號。? |
| ? | FontWeight | 獲取或設(shè)置指定的字體的權(quán)重或粗細(xì)。? |
| ? | Foreground | 獲取或設(shè)置描述前景色的畫筆。? |
| ? | HandlesScrolling | 獲取一個值控件是否支持滾動。 |
| ? | Height | 獲取或設(shè)置元素的建議高度。? |
| ? | HorizontalContentAlignment | 獲取或設(shè)置控件內(nèi)容的水平對齊。? |
| ? | IsLoaded | 獲取一個值,該值指示是否已加載此元素以供呈現(xiàn)。? |
| ? | IsMouseOver | 獲取一個值,該值指示鼠標(biāo)指針是否位于此元素(包括可視樹上的子元素)上。這是一個依賴項屬性。? |
| ? | IsTabStop | 獲取或設(shè)置一個值控制是否在選項卡上導(dǎo)航包含。? |
| ? | IsVisible | 獲取一個值,該值指示此元素在用戶界面?(UI)?中是否可見。這是一個依賴項屬性。? |
| ? | LayoutTransform | 獲取或設(shè)置在執(zhí)行布局時應(yīng)該應(yīng)用于此元素的圖形轉(zhuǎn)換方式。? |
| ? | Margin | 獲取或設(shè)置元素的外邊距。? |
| ? | Name | 獲取或設(shè)置元素的標(biāo)識名稱。?該名稱提供一個引用,以便當(dāng)?XAML?處理器在處理過程中構(gòu)造標(biāo)記元素之后,代碼隱藏(如事件處理程序代碼)可以對該元素進(jìn)行引用。 |
| ? | Opacity | 獲取或設(shè)置當(dāng)?UIElement?在用戶界面?(UI)?中呈現(xiàn)時為其整體應(yīng)用的不透明度因子。這是一個依賴項屬性。? |
| ? | Padding | 獲取或設(shè)置控件中的空白。? |
| ? | RenderTransform | 獲取或設(shè)置影響此元素的呈現(xiàn)位置的轉(zhuǎn)換信息。這是一個依賴項屬性。? |
| ? | TabIndex | 獲取或設(shè)置使用?tab?鍵時,確定順序接收焦點的元素的值,當(dāng)用戶將控件定位。? |
| ? | Tag | 獲取或設(shè)置任意對象值,該值可用于存儲關(guān)于此元素的自定義信息。? |
| ? | ToolTip | 獲取或設(shè)置在用戶界面?(UI)?中為此元素顯示的工具提示對象。? |
| ? | TouchesCaptured | 獲取在此元素上捕獲的所有觸摸設(shè)備。? |
| ? | TouchesCapturedWithin | 獲取在此元素或其可視化樹中的任何子元素上捕獲的所有觸摸設(shè)備。? |
| ? | VerticalContentAlignment | 獲取或設(shè)置控件內(nèi)容的垂直對齊方式。? |
| ? | Visibility | 獲取或設(shè)置此元素的用戶界面?(UI)?可見性。這是一個依賴項屬性。? |
| ? | VisualOpacityMask | 獲取或設(shè)置?Brush?值,該值表示?Visual?的不透明蒙板。? |
| ? | Width | 獲取或設(shè)置元素的寬度。? |
?
? ? ?? 一個Panel?的呈現(xiàn)就是測量和排列子控件,然后在屏幕上繪制它們。所以在布局的過程中會經(jīng)過一系列的計算,那么子控件越多,執(zhí)行的計算次數(shù)就越多,則性能就會變差。如果不需要進(jìn)行復(fù)雜的布局,則盡量少用復(fù)雜布局控件(如?Grid和自定義復(fù)雜的Panel);如果能簡單布局實現(xiàn)就盡量使用構(gòu)造相對簡單的布局(如?Canvas、UniformGrid等),這種布局可帶來更好的性能。?如果有可能,我們應(yīng)盡量避免調(diào)用?UpdateLayout方法。?
? ? ? 每當(dāng)Panel內(nèi)的子控件改變其位置時,布局系統(tǒng)就可能觸發(fā)一個新的處理過程。對此,了解哪些事件會調(diào)用布局系統(tǒng)就很重要,因為不必要的調(diào)用可能導(dǎo)致應(yīng)用程序性能變差。?
? ? ??換句話說,布局是一個遞歸系統(tǒng),實現(xiàn)在屏幕上對控件進(jìn)行大小調(diào)整、定位和繪制,然后進(jìn)行呈現(xiàn)。具體如下圖,要實現(xiàn)控件0的布局,那么先要實現(xiàn)0的子控件?01,02...的布局,要實現(xiàn)01的布局,那么得實現(xiàn)01的子控件001,002...的布局,如此循環(huán)直到子控件的布局完成后,再完成父控件的布局,?最后遞歸回去直到遞歸結(jié)束,這樣整個布局過程就完成了.
?
????? 布局系統(tǒng)為Panel中的每個子控件完成兩個處理過程:測量處理過程(Measure)和排列處理過程(Arrange)。每個子?Panel?均提供自己的?MeasureOverride?和?ArrangeOverride?方法,以實現(xiàn)自己特定的布局行為。
二.?Canvas?
????? Canvas是最基本的面板,只是一個存儲控件的容器,它不會自動調(diào)整內(nèi)部元素的排列及大小,它僅支持用顯式坐標(biāo)定位控件,它也允許指定相對任何角的坐標(biāo),而不僅僅是左上角。可以使用Left、Top、Right、?Bottom附加屬性在Canvas中定位控件。通過設(shè)置Left和Right屬性的值表示元素最靠近的那條邊,應(yīng)該與Canvas左邊緣或右邊緣保持一個固定的距離,設(shè)置Top和Bottom的值也是類似的意思。實質(zhì)上,你在選擇每個控件停靠的角時,附加屬性的值是作為外邊距使用的。如果一個控件沒有使用任何附加屬性,它會被放在Canvas的左上方(等同于設(shè)置Left和Top為0)。
????? Canvas的主要用途是用來畫圖。Canvas默認(rèn)不會自動裁減超過自身范圍的內(nèi)容,即溢出的內(nèi)容會顯示在Canvas外面,這是因為默認(rèn)?ClipToBounds=”False”;我們可以通過設(shè)置ClipToBounds=”True”來裁剪多出的內(nèi)容。
?
接下來我們來看兩個實例,第一個實例使用XAML代碼實現(xiàn):
<Window x:Class="WpfApp1.WindowCanvas"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="WindowCanvas" Height="400" Width="500"><Grid><Canvas Margin="0,0,0,0" Background="White"><Rectangle Fill="Blue" Stroke="Azure" Width="250" Height="200" Canvas.Left="210" Canvas.Top="101"/><Ellipse Fill="Red" Stroke="Green" Width="250" Height="100" Panel.ZIndex="1" Canvas.Left="65" Canvas.Top="45"/></Canvas><Canvas><Button Name="btnByCode" Click="btnByCode_Click">后臺代碼實現(xiàn)</Button></Canvas></Grid></Window>?
實例后的效果如下圖。
?
第二個實例,我們使用后臺代碼來實現(xiàn)。我使用C#來實現(xiàn)
?
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Shapes;namespace WpfApp1{/// <summary>/// WindowCanvas.xaml 的交互邏輯/// </summary>public partial class WindowCanvas : Window{public WindowCanvas(){InitializeComponent();}public void DisplayCanvas(){Canvas canv = new Canvas();//把canv添加為窗體的子控件this.Content = canv;canv.Margin = new Thickness(0, 0, 0, 0);canv.Background = new SolidColorBrush(Colors.White);//RectangleRectangle r = new Rectangle();r.Fill = new SolidColorBrush(Colors.Red);r.Stroke = new SolidColorBrush(Colors.Red);r.Width = 200;r.Height = 140;r.SetValue(Canvas.LeftProperty, (double)200);r.SetValue(Canvas.TopProperty, (double)120);canv.Children.Add(r);//EllipseEllipse el = new Ellipse();el.Fill = new SolidColorBrush(Colors.Blue);el.Stroke = new SolidColorBrush(Colors.Blue);el.Width = 240;el.Height = 80;el.SetValue(Canvas.ZIndexProperty, 1);el.SetValue(Canvas.LeftProperty, (double)100);el.SetValue(Canvas.TopProperty, (double)80);canv.Children.Add(el);}private void btnByCode_Click(object sender, RoutedEventArgs e){DisplayCanvas();}}}?
?實現(xiàn)后的效果如下圖。
?
最后?要說明一點Canvas內(nèi)的子控件不能使用兩個以上的Canvas附加屬性,如果同時設(shè)置Canvas.Left和Canvas.Right屬性,那么后者將會被忽略。
總結(jié)
以上是生活随笔為你收集整理的【转】WPF入门教程系列六——布局介绍与Canvas(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 看了《梦华录》才发现:什么咖啡拉花 都是
- 下一篇: 【转】.net框架读书笔记---CLR内