WPF當中有許多的布局容器控件,例如<Grid>、<StackPanel>、<WrapPanel>、<DockPanel>、<UniformGrid>。接下來分別介紹一下各個布局容器控件。
布局基礎
Grid
<Grid><Grid.RowDefinitions><RowDefinition Height="2*"/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="2*"/><ColumnDefinition/></Grid.ColumnDefinitions><Border Grid.Row="0" Grid.Column="0" Background="Red"/><Border Grid.Row="0" Grid.Column="1" Background="Yellow"/><Border Grid.Row="1" Grid.Column="0" Background="Blue"/><Border Grid.Row="1" Grid.Column="1" Background="Green"/>
</Grid>
Grid中的元素還可以跨行和跨列:
StackPanel
StackPanel默認水平排列,具有?Orientation=""屬性可以改變排列方向。
WrapPanel
WrapPanel默認水平排列,也具有?Orientation=""屬性可以改變排列方向。
DockPanel
DockPanel具有停靠的功能,位于DockPanel中的元素,可以設置它的方向。
UniformGrid
這個容器最大的作用就是在有限的空間里面均分剩余空間。
下面對一個頁面進行布局模擬練習:
<Grid><Grid.RowDefinitions><RowDefinition Height="80"/><RowDefinition/></Grid.RowDefinitions><Border Background="#FFECF1"/><Grid Grid.Row="1"><Grid.ColumnDefinitions><ColumnDefinition Width="200"/><ColumnDefinition/></Grid.ColumnDefinitions><Border Background="#FF7F24"/><Grid Grid.Column="1" Margin="5"><Grid.RowDefinitions><RowDefinition Height="100"/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid Grid.Row="0"><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><Border Margin="5" Grid.Column="0" Background="#1b1c1d"/><Border Margin="5" Grid.Column="1" Background="#2AC864"/><Border Margin="5" Grid.Column="2" Background="#1b1c1d"/><Border Margin="5" Grid.Column="3" Background="#F85A54"/><Border Margin="5" Grid.Column="4" Background="#1b1c1d"/></Grid><Grid Grid.Row="1"><Grid.ColumnDefinitions><ColumnDefinition Width="1.5*"/><ColumnDefinition/></Grid.ColumnDefinitions><Border Margin="5" Grid.Column="0" Background="#1b1c1d"/><Border Margin="5" Grid.Column="1" Background="#2AC864"/></Grid><Grid Grid.Row="2"><Grid.ColumnDefinitions><ColumnDefinition Width="1.5*"/><ColumnDefinition/></Grid.ColumnDefinitions><Border Margin="5" Grid.Column="0" Background="#1b1c1d"/><Border Margin="5" Grid.Column="1" Background="#F85A54"/></Grid></Grid></Grid>
</Grid>
樣式基礎
樣式負責修飾元素的外觀以及行為,可以在樣式中定義不同類型元素的屬性值集合。
<Window.Resources><Style x:Key="BaseStyle" TargetType="Button"><Setter Property="FontSize" Value="18"/><Setter Property="Foreground" Value="White"/><Setter Property="Background" Value="Red"/></Style><Style x:Key="BottonStyle" TargetType="Button" BasedOn="{StaticResource BaseStyle}"><Setter Property="Content" Value="Botton1"/></Style>
</Window.Resources>
<Grid><StackPanel><Button Background="Blue" Style="{StaticResource BottonStyle}"/><Button Style="{StaticResource BottonStyle}"/><Button Style="{StaticResource BottonStyle}"/></StackPanel>
</Grid>
數據模板
<Grid><ListBox x:Name="list"><ListBoxItem><StackPanel Orientation="Horizontal"><Border Width="10" Height="10" Background="Red"/><TextBlock Margin="10,0" Text="Red"/></StackPanel></ListBoxItem><ListBoxItem><StackPanel Orientation="Horizontal"><Border Width="10" Height="10" Background="Blue"/><TextBlock Margin="10,0" Text="Red"/></StackPanel></ListBoxItem><ListBoxItem><StackPanel Orientation="Horizontal"><Border Width="10" Height="10" Background="Green"/><TextBlock Margin="10,0" Text="Red"/></StackPanel></ListBoxItem></ListBox>
</Grid>
可以看到,這里每一項的構造都是完全相同的,唯一不同的就是它們的數據,因此可以將它抽離出來作為一個模板。
<Grid><ListBox x:Name="list"><ListBox.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><Border Width="10" Height="10" Background="{Binding Code}"/><TextBlock Margin="10,0" Text="{Binding Name}"/></StackPanel></DataTemplate></ListBox.ItemTemplate></ListBox>
</Grid>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
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.Navigation;
using System.Windows.Shapes;namespace WpfApp4 {/// <summary>/// MainWindow.xaml 的交互邏輯/// </summary>public partial class MainWindow : Window {public MainWindow() {InitializeComponent();List<Color> test = new List<Color>();test.Add(new Color() { Code = "#FFB6C1", Name = "淺粉紅" });test.Add(new Color() { Code = "#FFC0CB", Name = "粉紅" });test.Add(new Color() { Code = "#DC143C", Name = "猩紅" });test.Add(new Color() { Code = "#FFF0F5", Name = "臉紅的淡紫色" });//LightPink 淺粉紅 #FFB6C1 255,182,193//Pink 粉紅 #FFC0CB 255,192,203//Crimson 猩紅 #DC143C 220,20,60//LavenderBlush 臉紅的淡紫色 #FFF0F5 255,240,245list.ItemsSource = test;}public class Color {public string Code { get; set; }public string Name { get; set; }}}
}
由此就可以看到DataTemplate的作用。繼續編寫例子:
<Grid><DataGrid x:Name = "grid" AutoGenerateColumns="False" CanUserAddRows="False"><DataGrid.Columns><DataGridTextColumn Header="Code" Binding="{Binding Code}"/><DataGridTextColumn Header="Name" Binding="{Binding Name}"/><DataGridTemplateColumn Header="操作"><DataGridTemplateColumn.CellTemplate><DataTemplate><StackPanel Orientation="Horizontal"><Button Content="刪除" /><Button Content="復制" /><Button Content="保存" /></StackPanel></DataTemplate></DataGridTemplateColumn.CellTemplate></DataGridTemplateColumn></DataGrid.Columns></DataGrid>
</Grid>
靈活地使用DataTemplate數據模塊,對后續開發有很重要的幫助,當然DataTemplate的應用不止于此,后續還會介紹到。
綁定
使用綁定可以使得控件與控件之間建立一種綁定關系,可以不再為此編寫大量的代碼來維持。
<Grid><StackPanel><Slider x:Name="slider" Margin="5" ValueChanged="Slider_ValueChanged"/><TextBox x:Name="textbox1" Margin="5" Height="30" TextChanged="textbox1_TextChanged"/><TextBox x:Name="textbox2" Margin="5" Height="30"/><TextBox x:Name="textbox3" Margin="5" Height="30"/></StackPanel>
</Grid>
namespace WpfApp5 {/// <summary>/// MainWindow.xaml 的交互邏輯/// </summary>public partial class MainWindow : Window {public MainWindow() {InitializeComponent();}private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {textbox1.Text = slider.Value.ToString();textbox2.Text = slider.Value.ToString();textbox3.Text = slider.Value.ToString();}private void textbox1_TextChanged(object sender, TextChangedEventArgs e) {if (double.TryParse(textbox1.Text, out double result))slider.Value = result;}}
}
此時代碼實現了拖動滑塊,下方三個框里的數據會同步變化。對下方任意一個框里的數據進行修改,上方滑塊的位置也會同步變化。為了實現這個功能,代碼變得特別的冗余,可以使用綁定來簡化。
<Grid><StackPanel><Slider x:Name="slider" Margin="5"/><TextBox Text="{Binding ElementName=slider,Path=Value}" x:Name="textbox1" Margin="5" Height="30"/><TextBox Text="{Binding ElementName=slider,Path=Value}" x:Name="textbox2" Margin="5" Height="30"/><TextBox Text="{Binding ElementName=slider,Path=Value}" x:Name="textbox3" Margin="5" Height="30"/></StackPanel>
</Grid>
此時就不需要具體的實現代碼了,使用綁定就可以完成兩個控件的雙向綁定。?