Ở bài trước, chúng ta đã tạo được một ứng dụng có nút bấm và ô nhập liệu. Nhưng mọi control chúng ta phải xếp mọi thứ dọc từ trên xuống dưới.

Trong WinForms cũ, bạn sẽ dùng chuột kéo thả control đến vị trí mong muốn (ví dụ: x=100, y=50). Nhưng trong WPF, chúng ta hạn chế tối đa việc set tọa độ cứng. Tại vì khi người dùng phóng to cửa sổ, tọa độ cứng sẽ làm giao diện bị lệch, méo hoặc thừa khoảng trống, trông rất xấu.

Thay vào đó, WPF dùng các Layout Containers. Các container này sẽ giúp bạn sắp xếp các controls gọn gàng nhất.

Ở bài viết này, chúng ta sẽ tìm hiểu 3 loại container cơ bản và thông dụng nhất: StackPanel, WrapPanel và DockPanel.

StackPanel

Đây là layout bạn sẽ dùng nhiều nhất cho các bố cục đơn giản.

Nguyên lý hoạt động

Nó xếp các control con của nó thành một hàng duy nhất: hoặc là dọc (mặc định), hoặc là ngang. Giống như xếp chồng sách lên nhau hoặc xếp sách lên kệ

Thuộc tính quan trọng

●    Orientation: Quyết định hướng 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ụ thực tế

Bạn muốn làm một dãy 3 nút bấm "OK", "Cancel", "Help" nằm ngang cạnh nhau?

  <StackPanel Orientation="Horizontal">
   <Button Content="OK" Width="80" Margin="5"/>
   <Button Content="Cancel" Width="80" Margin="5"/>
   <Button Content="Help" Width="80" Margin="5"/>
</StackPanel>

Thuộc tính Margin="5" giúp tạo khoảng cách xung quanh nút bấm, để chúng không bị dính sát vào nhau.


WrapPanel

StackPanel có một nhược điểm: Nếu bạn xếp ngang mà cửa sổ quá bé, các nút bên phải sẽ bị che mất. WrapPanel sinh ra để giải quyết việc này.

Nguyên lý hoạt động

Nó xếp các control từ trái sang phải. Nhưng khi hết chỗ, nó sẽ tự động rớt xuống dòng tiếp theo.

Nó giống như khi bạn gõ văn bản trong Word, chữ tự động xuống dòng khi hết lề giấy.


  <WrapPanel Orientation="Horizontal">
   <Button Content="Ảnh 1" Width="100" Height="100" Margin="5"/>
   <Button Content="Ảnh 2" Width="100" Height="100" Margin="5"/>
   <Button Content="Ảnh 3" Width="100" Height="100" Margin="5"/>
   <Button Content="Ảnh 4" Width="100" Height="100" Margin="5"/>
   <Button Content="Ảnh 5" Width="100" Height="100" Margin="5"/>
  

</WrapPanel>


Ví dụ thực tế




Dùng làm thư viện ảnh, danh sách file, hoặc danh sách các thẻKhi bạn chạy code này và thử dùng chuột thu nhỏ chiều ngang cửa sổ lại, bạn sẽ thấy các nút tự động nhảy xuống hàng dưới.



DockPanel

Bạn muốn làm một giao diện cổ điển gồm: menu ở trên cùng, thanh trạng thái ở dưới đáy, và nội dung ở giữa thì hãy sử dụng DockPanel

Nguyên lý hoạt động

Nó cho phép các control con "dính" (dock) vào 4 cạnh: Top (Trên), Bottom (Dưới), Left (Trái), Right (Phải).

Phần tử cuối cùng được thêm vào DockPanel sẽ tự động lấp đầy khoảng trống còn lại ở giữa (trừ khi bạn tắt tính năng đó).

Cách sử dụng

Khác với 2 cái trên, DockPanel không dùng thuộc tính của chính nó, mà các control con phải đăng ký vị trí muốn dính bằng thuộc tính DockPanel.Dock.

  <DockPanel LastChildFill="True">
   <Button DockPanel.Dock="Top" Height="50" Content="Header (Menu)" Background="LightBlue"/>
   <Button DockPanel.Dock="Bottom" Height="30" Content="Footer (Status Bar)" Background="Gray"/>
   <Button DockPanel.Dock="Left" Width="100" Content="Sidebar" Background="LightGreen"/>
   <Button Content="Nội dung chính (Main Content)" Background="White"/>
</DockPanel>



Layout lồng Layout (Nested Layouts)

Bạn có thể nhét Layout này vào bên trong Layout kia

Ví dụ: Bạn muốn chia màn hình làm 2 phần trái - phải (dùng DockPanel hoặc StackPanel ngang). Nhưng bên trong phần bên trái, bạn lại muốn các nút xếp dọc (dùng StackPanel dọc).

  <DockPanel>
   <StackPanel DockPanel.Dock="Left" Width="150" Background="LightGray">
       <TextBlock Text="Danh sách bài học" FontWeight="Bold" Margin="10"/>
       <Button Content="Bài 1" Margin="5"/>
       <Button Content="Bài 2" Margin="5"/>
       <Button Content="Bài 3" Margin="5"/>
   </StackPanel>
 
   <StackPanel Background="White">
       <TextBlock Text="Nội dung bài học ở đây..." FontSize="20" Margin="20"/>
   </StackPanel>
</DockPanel>