Bố trí giao diện trong WPF

WPF cung cấp nhiều container để sắp xếp các thành phần giao diện. Dưới đây là các loại container phổ biến nhất:

1. StackPanel

Container này xếp các phần tử theo hướng dọc hoặc ngang. Mỗi phần tử chiếm toàn bộ chiều rộng (nếu dọc) hoặc chiều cao (nếu ngang) của container.

Thuộc tính Orientation quyết định hướng sắp xếp:

  • Vertical (mặc định): Xếp từ trên xuống dưới
  • Horizontal: Xếp từ trái sang phải

Ví dụ sắp xếp theo chiều dọc:

<Window
    x:Class="DemoLayout.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="StackPanel Demo"
    Width="600"
    Height="400">

    <StackPanel Padding="10">
        <TextBox x:Name="txtInput" Margin="0,0,0,8" Height="30"/>
        <Button x:Name="btnSubmit" Content="Gửi" Margin="0,0,0,8" Height="35"/>
        <Button x:Name="btnCancel" Content="Hủy" Margin="0,0,0,8" Height="35"/>
        <Button x:Name="btnReset" Content="Đặt lại" Height="35"/>
    </StackPanel>
</Window>

Để chuyển sang sắp xếp ngang, thêm thuộc tính sau:

<StackPanel Padding="10" Orientation="Horizontal">

2. WrapPanel

Container tự động xuống dòng khi không còn đủ không gian. Phù hợp cho danh sách các nút hoặc hình ảnh có kích thước đồng nhất.

<Window
    x:Class="DemoLayout.WrapDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WrapPanel Demo"
    Width="450"
    Height="300">

    <WrapPanel ItemWidth="100" ItemHeight="40" Margin="8">
        <Button Content="A" Margin="4"/>
        <Button Content="B" Margin="4"/>
        <Button Content="C" Margin="4"/>
        <Button Content="D" Margin="4"/>
        <Button Content="E" Margin="4"/>
        <Button Content="F" Margin="4"/>
        <Button Content="G" Margin="4"/>
        <Button Content="H" Margin="4"/>
    </WrapPanel>
</Window>

Thuộc tính quan trọng:

  • ItemWidth/ItemHeight: Kích thước đồng nhất cho tất cả phần tử
  • Orientation: Horizontal (mặc định) hoặc Vertical

3. DockPanel

Container cho phép neo các phần tử vào các cạnh (trái, phải, trên, dưới). Phần tử cuối cùng tự động chiếm không gian còn lại.

<Window
    x:Class="DemoLayout.DockDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="DockPanel Demo"
    Width="700"
    Height="500">

    <DockPanel LastChildFill="True">
        <Menu DockPanel.Dock="Top" Height="25">
            <MenuItem Header="Tệp"/>
            <MenuItem Header="Chỉnh sửa"/>
        </Menu>
        <StatusBar DockPanel.Dock="Bottom" Height="25">
            <TextBlock Text="Sẵn sàng"/>
        </StatusBar>
        <StackPanel DockPanel.Dock="Left" Width="150" Background="#EEE">
            <Button Content="Mục 1" Margin="5"/>
            <Button Content="Mục 2" Margin="5"/>
        </StackPanel>
        <TextBox Text="Nội dung chính" AcceptsReturn="True"/>
    </DockPanel>
</Window>

Lưu ý: Thuộc tính LastChildFill mặc định là True, phần tử cuối sẽ lấp đầy khoảng trống.

4. Grid

Container linh hoạt nhất, chia giao diện thành các hàng và cột. Đây là container được sử dụng phổ biến nhất trong WPF.

<Window
    x:Class="DemoLayout.GridDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Grid Demo"
    Width="500"
    Height="350">

    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="Tên:" VerticalAlignment="Center"/>
        <TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Height="25" Margin="5"/>
        
        <Label Grid.Row="1" Grid.Column="0" Content="Mô tả:" VerticalAlignment="Top"/>
        <TextBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" 
                 AcceptsReturn="True" TextWrapping="Wrap" Margin="5"/>
        
        <Button Grid.Row="2" Grid.Column="1" Content="Lưu" Width="80" 
                HorizontalAlignment="Right" Margin="5"/>
        <Button Grid.Row="2" Grid.Column="2" Content="Đóng" Width="80" Margin="5"/>
    </Grid>
</Window>

Cách định nghĩa kích thước:

Cú phápÝ nghĩa
200Giá trị cố định 200 pixel
AutoTự động theo nội dung
*Chia phần còn lại theo tỷ lệ
2*Gấp đôi phần của *

5. Canvas

Container đơn giản nhất, định vị tuyệt đối các phần tử bằng tọa độ. Phù hợp cho đồ họa, sơ đồ hoặc giao diện tùy chỉnh.

<Window
    x:Class="DemoLayout.CanvasDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Canvas Demo"
    Width="600"
    Height="400">

    <Canvas Background="WhiteSmoke">
        <Rectangle Canvas.Left="50" Canvas.Top="30" 
                   Width="120" Height="80" Fill="SteelBlue"/>
        <Ellipse Canvas.Left="200" Canvas.Top="50" 
                 Width="100" Height="60" Fill="Coral"/>
        <TextBlock Canvas.Left="350" Canvas.Top="60" 
                   Text="Văn bản tự do" FontSize="16"/>
        <Polygon Canvas.Left="100" Canvas.Top="150"
                 Points="0,0 60,0 30,50" Fill="MediumSeaGreen"/>
    </Canvas>
</Window>

Thuộc tính đặc biệt:

  • Canvas.Left/Canvas.Top: Vị trí góc trên-trái
  • Canvas.Right/Canvas.Bottom: Vị trí góc dưới-phải (ưu tiên thấp hơn)
  • Panel.ZIndex: Thứ tự chồng lớp (số lớn nằm trên)

Bảng so sánh nhanh

ContainerKhi nào dùngƯu điểm
StackPanelDanh sách đơn giảnDễ dàng, tự động căn chỉnh
WrapPanelDanh sách động, tag cloudTự động xuống dòng
DockPanelLayout ứng dụng cổ điểnNeo nhanh vào các cạnh
GridHầu hết các trường hợpLin hoạt, hỗ trợ căn chỉnh phức tạp
CanvasVẽ đồ họa, game 2DĐiều khiển vị trí tuyệt đối

Thẻ: WPF XAML StackPanel WrapPanel DockPanel

Đăng vào ngày 27 tháng 8 lúc 21:06