WPF中常用的布局容器介紹
一、簡(jiǎn)介
所有的WPF布局容器都派生自System.Windows.Controls.Panel。Panel繼承自FrameworkElement。 在Panel中有一個(gè)比較重要的屬性是UIElementCollection 類(lèi)型的Children屬性,UIElementCollection是一個(gè)有序的集合。我們可以使用繼承自Panel的類(lèi)來(lái)重寫(xiě)MeasureOverride(),ArrangeOverride()實(shí)現(xiàn)自定義面板。
常用的布局容器:
Border不是布局面板,但是經(jīng)過(guò)幾個(gè)大佬的提醒,用好他真的很重要,所以我就放在第一個(gè)了。
- StackPanel: 堆棧面板,水平或垂直放置元素。
- WrapPanel:可換行的行中放置元素,在水平方向上從左向右放置元素,換行后也是從左向右。在垂直方向上,從上到下放置元素,在切換列后也是從上到下。
- DockPanel: 根據(jù)容器的整個(gè)邊界調(diào)整元素。
- Grid:在行列表格中排列元素。
- UniformGrid:強(qiáng)制所有單元格具有相同尺寸。
- Canvas:使用固定坐標(biāo)絕對(duì)定位元素。
- ScrollViewer:通過(guò)添加滾動(dòng)條可以使當(dāng)前過(guò)長(zhǎng)布局內(nèi)的內(nèi)容縱向或者橫向滾動(dòng)。再有限的區(qū)域內(nèi)可以通過(guò)滾動(dòng)呈現(xiàn)更多的內(nèi)容。
二、代碼案例
1.Border
Border不是布局面板,但是經(jīng)常與布局類(lèi)的面板一起配合使用,所以先介紹Border。Border的主要作用是給元素添加邊框,這個(gè)元素可以理解為一個(gè)布局面板,一個(gè)控件等等。他包含設(shè)置邊框的2個(gè)屬性,BorderBrush用來(lái)設(shè)置顏色,BorderThickness用來(lái)設(shè)置寬度。CornerRadius設(shè)置圓角。而Padding和Margin一個(gè)設(shè)置邊框和里面元素的間距,一個(gè)設(shè)置邊框和其他臨近元素的間距。而B(niǎo)ackground則是設(shè)置border所有內(nèi)容的顏色。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="800"> <StackPanel> <!--BorderBrush用來(lái)設(shè)置顏色--> <!--BorderThickness用來(lái)設(shè)置寬度--> <!--CornerRadius設(shè)置圓角--> <!--Padding設(shè)置邊框和里面元素的間距--> <!--Margin設(shè)置邊框和其他臨近元素的間距--> <!--Background則是設(shè)置border所有內(nèi)容的顏色--> <Border Background="Bisque" BorderBrush="Coral" BorderThickness="3"> <Button Content="Button A" Width="120"/> </Border> <Border BorderBrush="Red" BorderThickness="3" Margin="5"> <Button Content="Button B"/> </Border> <Border BorderBrush="DarkRed" BorderThickness="3" Background="Red" Padding="5"> <Button Content="Button C"/> </Border> </StackPanel> <!--<Grid> </Grid>--> </Window>
運(yùn)行效果:
2.StackPanel
StackPanel面板可以在單行或者單列以堆棧的形式排列子元素。默認(rèn)情況下StackPanel面板按從上到下的順序排列元素。如果不指定寬度、則默認(rèn)寬度和StackPanel面板寬度一致,如果StackPanel寬度發(fā)生變化,則按鈕也會(huì)拉伸以適應(yīng)變化。而如果設(shè)置了寬度、就不會(huì)跟面板寬度變更發(fā)生變化。但是想要設(shè)計(jì)出自己想要的好看布局,還需要更多的元素,先看一個(gè)基本的例子。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="800"> <StackPanel x:Name="root_spanel" > <Button Content="點(diǎn)我切換方向" Click="OrientationTranslator_Click"/> <Button Content="點(diǎn)我添加元素到面板中" Click="AddElementToPanel_Click"/> <Button x:Name="btn_FixedWidth" Content="點(diǎn)我手動(dòng)設(shè)置寬度為120" Click="SetCurrentWidth_Click"/> <Button Content="大家一定要努力學(xué)習(xí)C#?。。?/> </StackPanel> </Window>
后臺(tái)邏輯代碼:
private void OrientationTranslator_Click(object sender, RoutedEventArgs e) { root_spanel.Orientation = root_spanel.Orientation == Orientation.Horizontal ? Orientation.Vertical : Orientation.Horizontal; } private void AddElementToPanel_Click(object sender, RoutedEventArgs e) { Button btn = new Button(); btn.Content = "我是新添加的Button"; root_spanel.Children.Add(btn); } private void SetCurrentWidth_Click(object sender, RoutedEventArgs e) { btn_FixedWidth.Width = 120; }
運(yùn)行效果:
3.WrapPanel
WrapPanel面板可以一次排列一行或一列然后再換行繼續(xù)排列,和StackPanel一樣,可以通過(guò)設(shè)置Orientation屬性來(lái)設(shè)置當(dāng)前是以水平還是垂直來(lái)排列子元素。因?yàn)槭歉鶕?jù)窗體變化演示布局排列,這個(gè)只有XAML。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="800"> <WrapPanel> <Button Content="《老黃?!? Width="120"/> <Button Content="臧克家" Width="120"/> <Button Content="塊塊荒田水和泥," Width="120"/> <Button Content="深翻細(xì)作走東西。" Width="120"/> <Button Content="老牛亦解韶光貴," Width="120"/> <Button Content="不待揚(yáng)鞭自?shī)^蹄。" Width="120"/> </WrapPanel> </Window>
運(yùn)行效果:
4.DockPanel
DockPanel面板與StackPanel面板類(lèi)似,但是DockPanel可以通過(guò)設(shè)置Dock附加屬性設(shè)置子元素??康倪?。Dock的值為L(zhǎng)eft、Right、Top、Bottom。通過(guò)設(shè)置子元素再DockPanel面板中的Dock屬性。可以修改子元素再DockPanel面板內(nèi)的位置??梢酝ㄟ^(guò)LastChildFill設(shè)置為true來(lái)告訴DockPanel面板使最后一個(gè)元素占滿剩余控件。而設(shè)置的??宽樞驎?huì)影響布局結(jié)果。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="900"> <DockPanel LastChildFill="True"> <Button DockPanel.Dock="Top" Content="今天學(xué)習(xí)了嗎?"/> <Button DockPanel.Dock="Left" Content="今天寫(xiě)代碼了?"/> <Button DockPanel.Dock="Right" Content="隨便放點(diǎn)東西"/> <Button DockPanel.Dock="Right" VerticalAlignment="Center" Content="真的理解了嗎?要不要再多敲幾遍。"/> <Button DockPanel.Dock="Bottom" Content="程序員不學(xué)習(xí)寫(xiě)代碼,還能干什么呢?"/> <Button DockPanel.Dock="Bottom" Content="程序員不學(xué)習(xí)寫(xiě)代碼,還能干什么呢?"/> </DockPanel> </Window>
運(yùn)行效果:
5.Grid
Grid面板是把顯示內(nèi)容分割到不可見(jiàn)的行列網(wǎng)格中。通過(guò)設(shè)置行列和對(duì)應(yīng)的寬高占比。來(lái)進(jìn)行網(wǎng)格布局。Grid布局再平時(shí)使用的比較多。大部分都是用來(lái)做布局的嵌套,設(shè)計(jì)外框各個(gè)部分的比例,然后在子元素中嵌套其他布局控件。來(lái)實(shí)現(xiàn)區(qū)域的劃分。
在使用Grid面板時(shí),需要用到一個(gè)叫做附加依賴(lài)項(xiàng)屬性的參數(shù)。在布局相關(guān)的內(nèi)容里不會(huì)去講什么是附加依賴(lài)項(xiàng)屬性,這個(gè)會(huì)在依賴(lài)項(xiàng)屬性中去講解,這里只有了解就行。因?yàn)檫@個(gè)針對(duì)于Grid布局來(lái)說(shuō)是固定寫(xiě)法。
我們添加一個(gè)三行三列的Grid面板。Grid.RowDefinitions和Grid.ColumnDefinitions里面的內(nèi)容是我們?cè)O(shè)置的Gird的行列數(shù)。各有3個(gè),代表我們是一個(gè)三行三列的網(wǎng)格。我們沒(méi)有設(shè)置寬高。就會(huì)默認(rèn)為是等分的。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="900"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <!--各列平分寬度--> <ColumnDefinition/> <ColumnDefinition /> <ColumnDefinition /> <!--要求左邊一列寬度固定,右邊一列以文本內(nèi)容寬度適配,剩下的寬度區(qū)域都給中間的列。為了提高代碼可讀性,不建議省略Width="*"雖然都是一樣的。--> <!--<ColumnDefinition Width="140"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/>--> </Grid.ColumnDefinitions> <!--網(wǎng)格布局設(shè)計(jì)好之后。我們需要往里面放置內(nèi)容。我們要使用Grid.Column、Grid.Row這2個(gè)附加依賴(lài)項(xiàng)屬性來(lái)實(shí)現(xiàn)把Button放置到不同的網(wǎng)格中--> <Button Grid.Column="0" Grid.Row="0" Content="Button Row 1 Column 1"/> <Button Grid.Column="1" Grid.Row="0" Content="Button Row 1 Column 2"/> <Button Grid.Column="2" Grid.Row="0" Content="Button Row 1 Column 3"/> <Button Grid.Column="0" Grid.Row="1" Content="Button Row 2 Column 1"/> <Button Grid.Column="1" Grid.Row="1" Content="Button Row 2 Column 2"/> <Button Grid.Column="2" Grid.Row="1" Content="Button Row 2 Column 3"/> <Button Grid.Column="0" Grid.Row="2" Content="Button Row 3 Column 1"/> <Button Grid.Column="1" Grid.Row="2" Content="Button Row 3 Column 2"/> <Button Grid.Column="2" Grid.Row="2" Content="Button Row 3 Column 3"/> </Grid> </Window>
運(yùn)行效果:
我們嘗試運(yùn)行代碼。就會(huì)得到9個(gè)一樣大小的Button。我們嘗試拖動(dòng)窗體大小。不管怎么拖動(dòng),應(yīng)該都是等量變化的。
6.UniformGrid
UniformGrid面板的特點(diǎn)是每個(gè)單元格始終保持一致的大小。通過(guò)設(shè)置行列數(shù)量來(lái)分割布局。元素通過(guò)放入的前后順序被分配到不同的位置。這個(gè)再某些特定場(chǎng)景配合數(shù)據(jù)虛擬化和列表虛擬化使用的還是比較多的。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="900"> <UniformGrid Columns="2" Rows="2"> <!--按照先來(lái)后到的順序,先行后列的放入到行列單元格--> <Button Content="Button A"/> <Button Content="Button B"/> <Button Content="Button C"/> <Button Content="Button D"/> </UniformGrid> </Window>
運(yùn)行效果:
7.Canvas
Canvas是一個(gè)基于坐標(biāo)的布局面板。他主要用于構(gòu)建圖形工具的繪圖、Canvas知識(shí)再指定的位置放置子元素。并且子元素要提供精確的尺寸。再Canvas中需要設(shè)置Canvas.Left和Canvas.Top屬性。用來(lái)設(shè)置相對(duì)于原點(diǎn)的left和top。
也可以使用Canvas.Right和Canvas.Bottom。但是Canvas.left和Right不能同時(shí)使用,Canvas.Top和Canvas.Bottom也不能同時(shí)使用。使用Panel.ZIndex來(lái)設(shè)置子元素的層級(jí)關(guān)系。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="900"> <Canvas> <!--Panel.ZIndex="1"設(shè)置子元素的層級(jí)關(guān)系,哪個(gè)數(shù)字大,哪個(gè)在上面--> <Button Content="Button A" Canvas.Left="255" Canvas.Top="70" Panel.ZIndex="2" Width="80px" Height="30px"/> <Button Content="Button B" Canvas.Left="110" Canvas.Top="100" Width="80px" Height="30px"/> <Button Content="Button C" Canvas.Left="295" Canvas.Top="81" Panel.ZIndex="1" Width="80px" Height="30px"/> </Canvas> </Window>
運(yùn)行效果:
Button A和Button C的重疊關(guān)系使用Panel.ZIndex來(lái)設(shè)置。
8.ScrollViewer
如果要再一個(gè)比較小的區(qū)域內(nèi)顯示特別多的內(nèi)容,就需要使用ScrollViewer來(lái)進(jìn)行橫向或縱向滾動(dòng)了,但是再實(shí)際使用過(guò)程中往往配合數(shù)據(jù)虛擬化和列表虛擬化來(lái)實(shí)現(xiàn)支持更多內(nèi)容的滾動(dòng)效果。不然如果內(nèi)容一旦特別多,ScrollViewer下的內(nèi)容又特別長(zhǎng),每次滾動(dòng)都會(huì)觸發(fā)布局的重新測(cè)量和排列。如果不使用虛擬化,會(huì)全部重新計(jì)算所有的布局元素,會(huì)特別卡,導(dǎo)致使用困難。
案例XAML代碼:
<Window x:Class="Wpf_Panel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf_Panel" mc:Ignorable="d" Title="MainWindow" Height="500" Width="900"> <Grid> <StackPanel> <ScrollViewer Name="scroll" Width="480" Height="350" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible" > <TextBlock Name="txtShowArticle" Foreground="Gray" Margin="20,10" Loaded="txtShowArticle_Loaded" /> </ScrollViewer> </StackPanel> </Grid> </Window>
后臺(tái)邏輯代碼:
string content = @"中國(guó)青年網(wǎng)6月22日電 據(jù)“健康廣東”微信公眾號(hào)消息,6月21日0-24時(shí),全省新增2例本土確診病例,深圳報(bào)告1例,東莞報(bào)告1例。 全省新增境外輸入確診病例5例,廣州報(bào)告2例,分別來(lái)自法國(guó)和阿曼;深圳報(bào)告1例,來(lái)自印度尼西亞;珠海報(bào)告1例,來(lái)自孟加拉國(guó);東莞報(bào)告1例,來(lái)自阿聯(lián)酋。新增境外輸入無(wú)癥狀感染者7例,廣州報(bào)告3例,2例來(lái)自柬埔寨,1例來(lái)自阿聯(lián)酋;佛山報(bào)告1例,來(lái)自柬埔寨;中山報(bào)告1例,來(lái)自加蓬;肇慶報(bào)告2例,均來(lái)自印度尼西亞。新增出院16例。 截至6月21日24時(shí),全省累計(jì)報(bào)告新冠肺炎確診病例2706例(境外輸入1140例)。目前在院221例。 (來(lái)源:中國(guó)青年網(wǎng))"; private void ShowArticle() { //獲取私信信息 StringBuilder strMessage = new StringBuilder(); strMessage.Append("標(biāo)題:" + "廣東昨日新增2例本土確診病例,深圳、東莞各1例" + "\r\n"); strMessage.Append("來(lái)源:" + "中國(guó)青年網(wǎng)" + "\r\n"); strMessage.Append("發(fā)送時(shí)間:" + "2021-06-22 15:31:32" + "\r\n"); strMessage.Append("發(fā)送內(nèi)容:" + content + "\r\n\n"); txtShowArticle.Text = strMessage.ToString(); } private void txtShowArticle_Loaded(object sender, RoutedEventArgs e) { ShowArticle(); }
運(yùn)行效果:
到此這篇關(guān)于WPF布局容器的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- WPF布局及布局容器介紹
- WPF項(xiàng)目在設(shè)計(jì)界面調(diào)用后臺(tái)代碼
- WPF數(shù)據(jù)綁定Binding的用法
- Visual?Studio創(chuàng)建WPF項(xiàng)目
- C#實(shí)現(xiàn)WPF項(xiàng)目復(fù)制和移動(dòng)文件夾
- C#中WPF顏色對(duì)話框控件的實(shí)現(xiàn)
- WPF實(shí)現(xiàn)文本描邊+外發(fā)光效果的示例代碼
- WPF在自定義文本框中實(shí)現(xiàn)輸入法跟隨光標(biāo)
- WPF自定義路由事件
- WPF路由事件之邏輯樹(shù)和可視樹(shù)遍歷
- WPF依賴(lài)屬性用法詳解
相關(guān)文章
.NetCore實(shí)現(xiàn)上傳多文件的示例詳解
本章和大家分享的是.NetCore的MVC框架上傳文件的示例,主要講的內(nèi)容有:form方式提交上傳,ajax上傳,ajax提交+上傳進(jìn)度效果,Task并行處理+ajax提交+上傳進(jìn)度,對(duì)大家非常有幫助,感興趣的朋友跟隨小編一起學(xué)習(xí)吧2017-04-04asp.net使用for循環(huán)實(shí)現(xiàn)Datalist的分列顯示功能
工程業(yè)績(jī)--用for循環(huán)代替了DataList多列顯示,得到2行四列的表格,需要內(nèi)存表的8行數(shù)據(jù)2009-12-12基于asp.net MVC 應(yīng)用程序的生命周期(詳解)
下面小編就為大家分享一篇基于asp.net MVC 應(yīng)用程序的生命周期詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12ASP.NET中application對(duì)象的使用介紹
這篇文章主要介紹了ASP.NET中application對(duì)象的使用,需要的朋友可以參考下2014-03-03CheckBox控件默認(rèn)選中,提交時(shí)永遠(yuǎn)獲得選中狀態(tài)的實(shí)現(xiàn)代碼
下面小編就為大家?guī)?lái)一篇CheckBox控件默認(rèn)選中,提交時(shí)永遠(yuǎn)獲得選中狀態(tài)的實(shí)現(xiàn)代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05ASP.NET 使用application與session對(duì)象寫(xiě)的簡(jiǎn)單聊天室程序
寫(xiě)了快一年的asp.net,application對(duì)象還真沒(méi)怎么用過(guò)。看了看書(shū),根據(jù)這兩個(gè)對(duì)象的特性寫(xiě)了一個(gè)簡(jiǎn)單的聊天室程序。真的是非常的簡(jiǎn)陋2014-07-07.NET下通過(guò)HttpListener實(shí)現(xiàn)簡(jiǎn)單的Http服務(wù)
這篇文章主要為大家詳細(xì)介紹了.NET下通過(guò)HttpListener實(shí)現(xiàn)簡(jiǎn)單Http服務(wù)的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-09-09asp.net中實(shí)體類(lèi)對(duì)象賦值到表單的實(shí)現(xiàn)代碼
昨天在網(wǎng)上看到了一個(gè)利用反射表單賦值到實(shí)體類(lèi)對(duì)象的一個(gè)方法,自己就在加了個(gè)方法,從實(shí)體對(duì)象到表單,覺(jué)的很不錯(cuò)非常省事,所以把他寫(xiě)成了一個(gè)類(lèi),供以后使用2010-11-11Xamarin.Forms在安卓機(jī)上進(jìn)行本機(jī)調(diào)試
這篇文章介紹了Xamarin.Forms在安卓機(jī)上進(jìn)行本機(jī)調(diào)試的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-02-02