使用.Net Core開發WPF App系列教程( 五、WPF中的布局)


使用.Net Core開發WPF App系列教程

一、.Net Core和WPF介紹

二、在Visual Studio 2019中創建.Net Core WPF工程

三、與.Net Framework的區別

四、WPF中的XAML

五、WPF中的布局

六、WPF中的常用控件(上)


布局原則

 

1、不顯式設置元素大小。

2、不使用絕對定位。

元素應該根據容器的內容來進行排列。絕對定位在開發前期會帶來一些便捷,但擴展性比較差。一旦顯示器尺寸或分辨率發生改變,界面的顯示效果可能會達不到預期的效果。

3、布局容器可以嵌套使用

 

常用布局容器

 WPF中的布局控件繼承自System.Windows.Controls.Panel抽象類。

常用的布局容器如下:

Grid 網格容器。可以創建不可見的行和列,然后通過設置行、列來進行元素排列。這是最靈活也是最常用的容器之一。
StackPanel 堆棧式面板。 在水平或垂直的堆棧中放置元素。當移除一個元素后,后面的元素會自動向前移動以填充空缺
WrapPanel  自動換行面板
DockPanel  停靠式面板。這個面板可以設置控件停靠的方式,類似Winform中的Dock屬性
Canvas 畫布。Canvas使用絕對定位來控制元素的位置。動畫時會經常用到這個容器
   

 

Grid

Grid容器是WPF中最常用的布局容器。創建一個WPF工程后,系統會自動添加Grid標簽作為頂級容器。

Grid容器通過定義行和列來設置控件的位置

 1   <!--ShowGridLines屬性可以開啟行列顯示-->
 2     <Grid ShowGridLines="True">
 3         <!--添加行列-->
 4         <Grid.RowDefinitions>
 5             <RowDefinition/>
 6             <RowDefinition/>
 7         </Grid.RowDefinitions>
 8         
 9         <Grid.ColumnDefinitions>
10             <ColumnDefinition/>
11             <ColumnDefinition/>
12         </Grid.ColumnDefinitions>
13 
14         <Label Content="Row=0,Column=0"/>
15         <Label Content="Row=1,Column=1"/>
16     </Grid>

 

說明:

如果沒有指定行和列,元素會默認放置在Grid的0行0列。

 

在Grid容器中,行和列的尺寸支持三種模式:

1、指定尺寸

 1 <!--指定尺寸-->
 2         <Grid Grid.Column="1" ShowGridLines="True">
 3             <Grid.ColumnDefinitions>
 4                 <ColumnDefinition Width="120"/>
 5                 <ColumnDefinition/>
 6             </Grid.ColumnDefinitions>
 7 
 8             <Label Content="寬度120"/>
 9             <Label Content="寬度為Grid容器大小 - 120" Grid.Column="1"/>
10         </Grid>

這種模式可以指定行和列的高度或寬度。

 

說明:

1、WPF中默認寬高單位是像素(Pixel),完整的寫法應該是Width="120px",但是這個px可以省略。

2、WPF還支持英寸(in)、厘米(cm)、點(pt)等單位,這里不做詳細介紹。可參閱推薦閱讀。

3、這種模式不建議使用,因為這種方式是使用設備無關單位准確的設置尺寸。

 

2、指定比例

 1 <Grid Grid.Column="2" ShowGridLines="True">
 3             <Grid.RowDefinitions>
 4                 <RowDefinition Height="*"/>
 5                 <RowDefinition Height="3*"/>
 6             </Grid.RowDefinitions>
 7 
 8             <!--不指定比例,會等比拆分行列-->
 9             <Grid.ColumnDefinitions>
10                 <ColumnDefinition/>
11                 <ColumnDefinition/>
12             </Grid.ColumnDefinitions>
13         </Grid>

可通過(*)來指定行列所占比例。未使用(*)指定比例的,按等比划分。

上面的示例代碼中,定義了兩行,兩列。

第一行占Grid容器高度的1/4,第二行占Grid容器高度的3/4。

在定義列的時候,未指定比例,所以兩列各占Grid容器寬度的1/2

 

3、自動設置

自動設置就是在指定寬高時使用Auto,使用了Auto的行列寬高是根據內部所放置元素來決定。

1     <Grid ShowGridLines="True">
2             <Grid.RowDefinitions>
3                 <RowDefinition/>
4                 <RowDefinition/>
5                 <RowDefinition Height="Auto"/>
6             </Grid.RowDefinitions>
7 
8             <Label Content="高度 50" Grid.Row="2"/>
9         </Grid>

上面的示例代碼中,在Grid中定義了三行。

第三行的高度使用了Auto。

如果不在第三行放置任何元素,第一行和第二行會各占Grid元素的1/2,即 Grid.Height /2

當在第三行放置一個高度為50的元素后,第三行有了50的高度。

這個時候,前面兩行的高度就會發生變化,變成 (Grid.Height - 50 ) / 2

  

說明:

1、指定為Auto時,可以通過MinHeight來指定最小高度,MinHeight來指定最小寬度。

2、在布局時,通常會混合使用以上各種模式。

3、可以使用 Grid.UseLayoutRounding="True"來啟用抗鋸齒功能。啟用后,會將容器內所有內容對齊到最近的像素邊界。

 

跨越行和列

在定義行和列以后,有時候會需要跨越行來列來進行布局。這個時候可以使用Grid.RowSpan和Grid.ColumnSpan這兩個附加屬性來進行設置。

 1 <Grid>
 2                 <Grid.RowDefinitions>
 3                     <RowDefinition/>
 4                     <RowDefinition/>
 5                 </Grid.RowDefinitions>
 6 
 7                 <Grid.ColumnDefinitions>
 8                     <ColumnDefinition/>
 9                     <ColumnDefinition/>
10                 </Grid.ColumnDefinitions>
11 
12                 <Label Name="label1" Content="不跨越列" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center"/>
13                 <Label Name="label2" Content="跨越兩列" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
14 
15                 <Label Name="label3" Content="不跨越行" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"/>
16                 <Label Name="label4" Content="跨越兩行" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" VerticalAlignment="Center"/>
17             </Grid>

 

說明:

Grid布局技巧:

1、根據需要動態變化的內容,設置行列寬高來進行布局。

2、針對長度或寬度不固定的區域,可以設置寬度為Auto

3、WPF提供了一個GridSplitter類,可以動態的調整Grid的行高和列寬

 1  <Grid>
 2                 <Grid.RowDefinitions>
 3                     <RowDefinition/>
 4                     <RowDefinition Height="auto"/>
 5                     <RowDefinition/>
 6                 </Grid.RowDefinitions>
 7 
 8                 <Grid.ColumnDefinitions>
 9                     <ColumnDefinition/>
10                     <ColumnDefinition Width="auto"/>
11                     <ColumnDefinition/>
12                 </Grid.ColumnDefinitions>
13                 
14                 <Grid Grid.Row="0" Grid.Column="0" Background="Green"></Grid>
15                 <Grid Grid.Row="0" Grid.Column="2" Background="Silver"></Grid>
16                 <Grid Grid.Row="2" Grid.Column="0" Background="Pink"></Grid>
17                 <Grid Grid.Row="2" Grid.Column="2" Background="LightSkyBlue"></Grid>
18 
19                 <GridSplitter HorizontalAlignment="Stretch" VerticalAlignment="Center" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Height="2"></GridSplitter>
20                 <GridSplitter VerticalAlignment="Stretch" HorizontalAlignment="Center" Grid.Column="1" Grid.Row="0" Grid.RowSpan="3" Width="2"></GridSplitter>
21             </Grid>

 

StackPanel

StackPanel容器的使用比較簡單,它可以在單行或單列中以堆棧形式放置元素。

使用方法如下:

1 <!--垂直堆放元素(默認)-->
2         <StackPanel Grid.Column="0">
3             <Button Content="Button1" Margin="10"/>
4             <Button Content="Button2" HorizontalAlignment="Left"/>
5             <Button Content="Button3" HorizontalAlignment="Right"/>
6         </StackPanel>

 

1        <!--水平堆放元素 -->
2         <!--需要指定屬性  Orientation="Horizontal"-->
3         <StackPanel Grid.Column="1" Orientation="Horizontal">
4             <Button Content="Button1" Margin="10"/>
5             <Button Content="Button2" VerticalAlignment="Top"/>
6             <Button Content="Button3" VerticalAlignment="Bottom"/>
7         </StackPanel>

 

通過FlowDirection屬性可以指定元素的浮動方向

 1             <!--FlowDirection可以指定元素的浮動方向-->
 2             <!--LeftToRight是默認值,表示元素從左向右浮動-->
 3             <StackPanel FlowDirection="LeftToRight">
 4                 <Button Content="Button1" Width="120" Height="28" HorizontalAlignment="Left"/>
 5             </StackPanel>
 6 
 7             <!--RightToLeft表示元素從右向左浮動-->
 8             <StackPanel FlowDirection="RightToLeft" Grid.Row="1">
 9                 <Button Content="Button1" Width="120" Height="28" HorizontalAlignment="Left"/>
10             </StackPanel>

 

 

WrapPanel

WrapPanel和StackPanel差不多,它采用了流式 布局,控件也是一次一行或一列的方式布置。但它與StackPanel又有區別,WrapPanel的 控件從左向右或從上往下進行排列,排列滿了以后再在下一行或下一列排列。

WrapPanel可用於工具欄類似的場景,因為控件可以依次排列下去。

 1 <!--默認水平排列-->
 2         <WrapPanel Grid.Row="0" Grid.Column="0">
 3             <Button Content="abc"/>
 4             <Button Content="abc"/>
 5             <Button Content="abc"/>
 6             <Button Content="abc"/>
 7             <Button Content="abc"/>
 8             <Button Content="abc"/>
 9             <!--當水平方向排列不下時,自動排列到下一行-->
10             <Button Content="abc"/>        
11         </WrapPanel>

 

1  <!--設置為垂直排列-->
2         <WrapPanel Grid.Row="0" Grid.Column="1" Orientation="Vertical">
3             <Button Content="abc"/>
4             <Button Content="abc"/>
5             <Button Content="abc"/>
6             <!--當垂直方向排列不下時,自動排列到下一列-->
7             <Button Content="abc"/>
8         </WrapPanel>

 

DockPanel

DockPanel是一種停靠式布局容器。通過附加屬性DockPanel.Dock設置元素的停靠方向。

 

當元素被指定為停靠在頂部時,元素會占據布局容器的整個寬度,高度會根據內容和MinHeight屬性而定。當元素被停靠在左邊時,元素會占據整個布局容器的高度,而寬度會根據內容和MinWidth屬性而定。

1 <DockPanel Grid.Row="0"  Margin="10">
2             <Button Content="左停靠" DockPanel.Dock="Left" MinWidth="80"/>
3             <Button Content="右停靠" DockPanel.Dock="Right"/>
4             <Button Content="上停靠" DockPanel.Dock="Top"/>
5             <Button Content="下停靠" DockPanel.Dock="Bottom"/>
6 </DockPanel>

 

默認情況下DockPanel.LastChildFill屬性值為true,該屬性會設置最后一個元素否占滿整個布局容器。如果設置LastChildFillfalse,可以看到

 

使用DockPanel容器進行布局時,元素的先后順序影響會很大。在上面的示例中,最先放置向左停靠的元素,所以【上停靠】這個按鈕會占據整個面板的高度,其它的元素會放置在它的右邊。

如果最先放置向上停靠的元素,那這個向上停靠的元素會占據整個面板的寬度,其它的元素會放置在它的下面

1 <!--可以看到元素的先后順序對布局會產生很大的影響-->
2         <DockPanel Grid.Row="2" Margin="10">
3             <Button Content="左停靠" DockPanel.Dock="Top" MinWidth="80"/>
4             <Button Content="右停靠" DockPanel.Dock="Right"/>
5             <Button Content="上停靠" DockPanel.Dock="Left"/>
6             <Button Content="下停靠" DockPanel.Dock="Bottom"/>
7         </DockPanel>

 

重復上面的過程,可以更清楚的看到元素的先后對布局的影響以及DockPanel元素排列的規則

 1  <DockPanel Grid.Row="3" Margin="10">
 2             <Button Content="左停靠" DockPanel.Dock="Left" MinWidth="80"/>
 3             <Button Content="右停靠" DockPanel.Dock="Right"/>
 4             <Button Content="上停靠" DockPanel.Dock="Top"/>
 5             <Button Content="下停靠" DockPanel.Dock="Bottom"/>
 6             <Button Content="上停靠" DockPanel.Dock="Top" MinWidth="80"/>
 7             <Button Content="右停靠" DockPanel.Dock="Right"/>
 8             <Button Content="左停靠" DockPanel.Dock="Left"/>
 9             <Button Content="下停靠" DockPanel.Dock="Bottom"/>
10 </DockPanel>

 

Canvas

Canvas面板,畫布面板,它可以通過使用精確的坐標來放置元素。大多數情況下,我們不需要絕對定位來放置元素,因為顯示器的大小和分辨率有可能會改變。但是如果需要設計繪圖相關的界面,或需要對元素進行動畫時,就要用到Canvas面板。

Canvas面板是最輕量級的布局容器,因為它不包含任何復雜的布局邏輯。

通過Canvas.Left附加屬性,設置元素左邊和Canvas面板左邊的單位數。不指定單位時,默認是px。通過Canvas.Top附加屬性,設置元素上邊和Canvas面板上邊的單位數。

也可以設置Canvas.Bottom和Canvas.Right附加屬性來指定距離面板底部和右邊的單位數(設置無關單位,當將系統DPI指定為96dpi時,設置無關單位恰好等於通常使用的像素)。

 

說明:

1、不能同時指定Canvas.Left和Canvas.Right,只能選擇一種指定。

2、不能同時指定Canvas.Top和Canvas.Bottom,只能選擇一種指定。

 

在Canvas面板中,需要指定元素的大小,即指定Width和Height屬性的值 。如果未指定元素寬高,元素的大小就是剛好能展示其全部內容的大小

 1    <Canvas>
 2         <!--基本使用-->
 3         <!--未指定寬高-->
 4         <Button Content="Canvas" Canvas.Left="100" Canvas.Top="200"/>
 5         <Button Content="Canvas" Canvas.Left="200px" Canvas.Top="200px"/>
 6         <Button Content="Canvas" Canvas.Left="2in" Canvas.Top="2.5in"/>
 7         <Button Content="Canvas" Canvas.Right="100" Canvas.Bottom="200"/>
 8         
 9         <!--指定寬高 -->
10         <Button Content="Canvas" Canvas.Left="50" Canvas.Top="100" Width="150" Height="28"/>
11     </Canvas>

說明:

當Canvas面板的大小改變時,面板內放置的元素大小不會改變。

 

元素疊放的順序Z-Order

如果Canvas面板中有重疊的元素,可以通過設置Canvas.ZIndex附加屬性來控制層疊方式。

默認每個元素會有默認的ZIndex值0,具有更高ZIndex值的元素會始終顯示在較低ZIndex值元素的上面。ZIndex值可以為負數 

1   <!--指定疊放順序-->
2         <Button Content="ZIndex=0" Canvas.Left="300" Canvas.Top="190"/>
3         <Button Content="ZIndex=1" Canvas.Left="310" Canvas.Top="200"/>
4         <Button Content="ZIndex=2" Canvas.Left="290" Canvas.Top="200"/>
5 
6         <!--ZIndex值都為0的情況下,后放置的元素會顯示在上面-->
7         <Button Content="ZIndex=0-1" Canvas.Left="380" Canvas.Top="190"/>
8         <Button Content="ZIndex=0-2" Canvas.Left="380" Canvas.Top="190"/>

 

推薦閱讀

寬高支持的單位

https://docs.microsoft.com/en-us/dotnet/api/system.windows.frameworkelement.width?view=netcore-3.1#xaml-values

WPF控件庫示例

https://github.com/Microsoft/WPF-Samples/tree/master/Getting%20Started/ControlsAndLayout

 

本文示例代碼:

https://github.com/zhaotianff/DotNetCoreWPF/tree/master/五、WPF中的布局容器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM