Cách chuyển đổi giữa các window trong wpf

Trong WPF bạn thiết kế bố cục của ứng dụng bằng các panel container khác nhau.Mỗi panel lại có đặc tính bố trí logic hoàn toàn khác nhau, như StackPanel sắp xếp các control trong nó theo dạng ngăn xếp, Grid sắp xếp theo dạng lưới v.v

1.Tìm hiểu về Layout trong WPF

- Một cửa sổ chỉ có thể chứa duy nhất một điều khiển, để tạo nhiều điều khiển trên giao diện người dùng, chúng ta cần 1 panel container trong cửa sổ và thêm các điều khiển vào panel này.

Hạn chế này nguyên nhân là lớp Window có nguồn gốc từ ContentControl

Trong WPF, bố cục được xác định bởi cách bạn sử dụng các panel container,khi bạn đã nắm được 1 số nguyên tắc cơ bản sử dụng các panel container sau :

- Các điều khiển không nên xác định kích thước rõ ràng,thay vào đó chỉ nên phát triển phù hợp tùy theo nội dung, ví dụ 1 button tự động mở rộng cho phù hợp khi bạn thêm text bằng cách thiết lập kích thước tối đa và tối thiểu. 

- Các điều khiển không được xác định vị trí trên màn hình tọa độ.Thay vào đó, chúng được sắp xếp bằng các panel dựa vào kích thước , thứ tự, các thông tin lựa chọn khác.Nếu cần thêm khoảng trắng giữa các control dùng thuộc tính Margin.

- Panel container chia sẻ không gian trong nó cho các điều khiển.Chúng cung cấp kích thước cho điều khiển dựa trên nội dung của điều khiển , nếu không gian bên trong nó không đủ, chúng sẽ phân phối thêm không gian bên trong chúng cho một hoặc nhiều điều khiển tùy theo giới hạn cho phép chúng.

- Panel container có thể lồng nhiều cấp.Thông thường là dùng gird, một panel container hiệu quả nhất để sắp xếp các nhóm nhỏ các control

Mặc dù có những trường hợp ngoại lệ cho những nguyên tắc này, nhưng tuân thủ được sẽ tạo ra được giao diện bố cục thích hợp cho WPF

2.Tiến trình sắp xếp bố cục

- Bố cục được hình thành bởi hai giai đoạn : đo lường và sắp xếp.Trong giai đoạn đo lường : các vòng lặp qua các phần tử điều khiển để lấy các thông tin kích thước thích hợp.Trong giai đoạn sắp xếp : đặt các điều khiển ở vị trí thích hợp trong panel container, vẫn có trường hợp không đủ chỗ trống cần thiết dẫn đến một số điều khiển hiển thị không đầy đủ.Để tránh tình trạng này, chúng ta sẽ thiết lập kích thước tối thiểu phù hợp.

3.Bố cục của các Panel Container

- Tất cả các panel container đều kế thừa từ lớp trừu tượng System.Windows.Controls.Panel


Các thuộc tính public của class Panel

Tên thuộc tínhMiêu tả
 Background   - Brush element sẽ được dùng để vẽ nền của Panel , chúng ta sẽ phải thiết lập giá trị của thuộc tính này là non-null nếu bạn muốn nó nhận sự kiện của chuột , (Trường hợp bạn muốn nó nhận một sự kiện của chuột nhưng không muốn hiển thị 1 solid background bạn thiết lập background đến Transparent)
 Children - Tập hợp các Item được lưu trữ trong Panel , đây là cấp đầu tiên của các item , và chính các item này sẽ chứa trong nó các item khác.
 IsItemsHost - Có giá trị kiểu Boolean , giá trị là true nếu panel được dùng để hiển thị các Item kết hợp với 1 ItemsControl (Chẳng hạn như Node trong một TreeView hoặc là một list mục trong một ListBox) 

Cách chuyển đổi giữa các window trong wpf
Quan trọng : 

- Bạn có thể override MeasureOveride() và ArrangOveride() kế thừa từ lớp FrameworkElement để thay đổi cách xử lý Panel trong các giai đoạn đo lường và sắp xếp đã nói ở trên lúc sắp xếp các element của nó
- WPF cung cấp một số Panel cơ bản nhất để sắp xếp bố cục và hầu hết các Element Object đều nằm trong không gian tên System.Windows.Controls

Danh sách các Panel chính của WPF
Tên PanelMiêu tả
StackPanel - Đặt các element trong một ngăn xếp nằm ngang (horizontal) hoặc thẳng đứng (vertical), container loại này được dùng để xây dựng một phần trên của sổ của ứng dụng.
WrapPanel - Cho phép sắp xếp các phần tử từ trái sang phải. Khi một dòng phần tử đã điền đầy khoảng không gian cho phép theo chiều ngang, WrapPanel sẽ cuốn phần tử bị tràn khởi giới hạn kích quy định của nó  xuống đầu dòng tiếp theo (tương tự như việc cuốn text).
DockPanel - DockPanel cho phép các phần tử bám lên các cạnh của panel DockPanel bao chứa chúng, tương tự như khái niệm Docking trong Windows Forms. Nếu như có nhiều phần tử cùng bám về một cạnh, chúng sẽ tuân theo thứ tự mà chúng được khai báo trong file XAML
Grid - Panel dạng Grid là dạng panel hết sức linh hoạt, và có thể sử dụng để đạt được gần như tất cả khả năng mà các dạng panel khác có thể làm được, mặc dù mức độ khó dễ không giống nhau. Grid cho phép ta phân định các dòng và cột theo dạng một lưới kẻ ô, và sau đó sẽ sắp đặt các phần tử UI vào các ô tùy ý. Grid sẽ tự động chia đều các dòng và cột (dựa trên kích thước của phần nội dung). Tuy nhiên, ta có thể sử dụng dấu sao (*) để phân định kích thước theo tỉ lệ hoặc phân định giá trị tuyệt đối về chiều cao hoặc chiều rộng cho hàng và cột. Ta có thể nhận biết sự khác biệt của 2 dạng phân định kích thước nêu trên bằng cách thay đổi kích thước của form chứa panel Grid. Thêm vào đó, thuộc tính ShowGridLines = "True" cho phép hiển thị các đường kẻ ô.
UniformGrid  - Đặt các yếu tố trong một bảng vô hình nhưng buộc tất cả các tế bào có cùng kích thước. Container bố trí này được sử dụng thường xuyên.
Canvas - Panel dạng Canvas sử dụng phương thức sắp xếp các phần tử UI theo vị trí tuyệt đối bằng cách đặt thuộc tính Top (đỉnh) và Left (bên trái) của chúng. Thêm vào đó, thay vì đặt thuộc tính Top, Left, ta có thể đặt thuộc tính Bottom (đáy), Right (bên phải). Nếu ta đặt đồng thời thuộc tính Left và Right, thuộc tính Right sẽ bị bỏ qua. Phần tử UI sẽ không thay đổi kích thước để thỏa mãn 2 thuộc tính trên cùng một lúc. Tương tự thuộc tính Top sẽ được ưu tiên hơn thuộc tính Bottom. Các phần tử được khai báo sớm hơn trong file XAML sẽ có thể bị che khuất phía dưới các phần tử được khai báo muộn hơn nếu vị trí của chúng xếp chồng lên nhau.

- Ngoài các container chính chúng ta còn có 1 số container phụ chẳng hạn như TabPanel
( các tab trong một TabControl ) , ToolbarPanel ( các nút trong một thanh công cụ ) , và ToolbarOverflowPanel ( các lệnh trong menu sổ xuống của một thanh công cụ )

4.Tạo một bố cục đơn giản với Stack Panel
- StackPanel bố trí các phần tử con nằm trong nó bằng cách sắp xếp chúng theo thứ tự trước sau. Các phần
tử sẽ xuất hiện theo thứ tự mà chúng được khai báo trong file XAML theo chiều dọc (ngầm định) hoặc theo
chiều ngang
4.1 Sắp xếp theo chiều dọc

Code XAML

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

"Lesson1.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Lesson1 - StackPanel" Height="120" Width="280">

"Beige">

    "200" BorderBrush="DarkSlateBlue" Background="#a9e969" BorderThickness="2">

    

        Control 1

    

    

        

    

     "200" BorderBrush="#feca00" BorderThickness="2">

        

        "Right">Control 3

    

4.1 Sắp xếp theo chiều ngang
Sau đây là đoạn mã XAML minh họa việc sử dụng StackPanel để sắp xếp các phần tử UI cùng ví dụ ở trên theo chiều ngang. Điểm khác biệt duy nhất ở đây là thiết lập thêm thuộc tính Orientation="Horizontal" của đối tượng StackPanel được sử dụng.
Code XAML

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

    "Beige" Orientation="Horizontal">

        

        "90" Height="80" BorderBrush="DarkSlateBlue"

                Background="#a9e969" BorderThickness="2">

            

            Control 1

        

        

        

        

        "90" BorderBrush="#feca00" BorderThickness="2">

            

            "Right">Control 3

        

    

Trong trường hợp sắp xếp theo chiều ngang, nếu tổng chiều rộng của các phần tử con lớn hơn chiều rộng của form chứa, thì các phần tử nằm ngoài form sẽ không được nhìn thấy.

5.Các thuộc tính của Layout :
- Mặc dù bố cục ứng dụng được xác định bởi các container, các yếu tố con vẫn có thể có được tiếng nói của mình. Trong thực tế, các panel layout kết hợp với các child element của nó rất nhịp nhàng bằng cách tôn trọng một tập nhỏ các thuộc tính bố trí, được liệt kê dưới đây

Tên thuộc tính Miêu tả chi tiết
HorizontalAlignment - Xác định cách một child element đặt bên trong một container bố cục
lúc thêm không gian dạng hàng ngang. Bạn có thể chọn
Center, Left, Right, hoặc Stretch.
VerticalAlignment  - Xác định cách một child element đặt bên trong một container bố cục 
lúc thêm không gian theo chiều dọc có sẵn. Bạn có thể chọn 
Center, Top, Bottom, hoặc Stretch.
Margin - Xác định khoảng cách xung quanh một phần tử so với parent element chứa nó. Margin thuộc tính là một instance của System.Windows.Thickness cấu trúc, với các thành phần riêng biệt cho Top, Bottom, Left, và Right.
MinWidth & MinHeight - Thiết lập kích thước tối thiểu của một phần tử. Nếu một phần tử quá lớn container bố cục của nó, nó sẽ được cắt cho phù hợp.
MaxWidth & MaxHeight - Thiết lập kích thước tối đa của một phần tử. Nếu container
đã nhiều không gian trong nó có sẵn, các phần tử sẽ không được mở rộng vượt ra ngoài những giới hạn, ngay cả khi HorizontalAlignment và Thuộc tính VerticalAlignment được đặt là Stretch.
Width & Height - Một cách rõ ràng thiết lập kích thước của một phần tử. Thiết lập này sẽ ghi đè một giá trị Stretch dùng cho các HorizontalAlignment hoặc VerticalAlignment
thuộc tính. Tuy nhiên, kích thước này không được áp dụng nếu nó vượt ra bên ngoài giới hạn theo quy định của MinWidth, Minheight, MaxWidth, và
MaxHeight.

Tất cả những thuộc tính được thừa kế từ lớp FrameworkElement cơ sở và do đó được hỗ trợ bởi tất cả các widget đồ hoạ, bạn có thể sử dụng trong một cửa sổ WPF.

6.Canh lề cho bố cục :

- Một StackPanel với thuộc tính định hướng VerticalAlignment dọc không có tác dụng vì mỗi phần tử được cho là nhiều chiều cao như nó cần và không cầ nhiều hơn. Tuy nhiên, HorizontalAlignment lại 
quan trọng và có ảnh hưởng. Nó quyết định đó mỗi thành phần child element được đặt trong hàng của mình.

- Thông thường, các HorizontalAlignment có giá trị mặc định là Left cho một nhãn Label và Stretch cho một Button. Đó là lý do tại sao mỗi nút có độ rộng đổ đầy chiều rộng của Panel cha chứa nó. Tuy nhiên, bạn có thể thay đổi điều đó :

?

1

2

3

4

5

6

7

8

"Vertical">

        

        

        

        

        

        

    

Cách chuyển đổi giữa các window trong wpf

Cách chuyển đổi giữa các window trong wpf
Lưu ý : StackPanel cũng có đặc tính HorizontalAlignment và VerticalAlignment riêng của mình. Theo mặc định, cả hai này được thiết lập để Stretch, và do đó, StackPanel đổ đầy container chứa nó hoàn toàn. Trong ví dụ này, có nghĩa là StackPanel lấp đầy cửa sổ chứa nó. Nếu bạn sử dụng các cài đặt khác nhau, StackPanel sẽ được hiện thực đủ lớn để phù hợp với giới hạn rộng nhất.

7.Lề Margin trong Layout :

- Có một vấn đề rõ ràng với ví dụ StackPanel trong hình thức hiện tại của nó. Một cửa sổ được thiết kế tốt không chỉ chứa các thành phần child element-nó cũng bao gồm một chút khoảng trống thêm trong giữa các yếu tố cho dễ nhìn để giới thiệu thêm không gian này và làm cho ví dụ StackPanel dễ nhìn, bạn có thể thiết lập lề Margin

- Khi thiết lập lề Margin, bạn có thể thiết lập độ rộng cho tất cả các bên của child element, như thế này:

?

1

Ngoài ra, bạn có thể thiết lập lề khác nhau cho 4 phía của một điều khiển theo thứ tự Left, Top, Right, Bottom

?

1

- Trong code - behind giá trị của thuộc tính Margin được thiết lập bởi 1 khởi tạo của lớp Thickness

?

1

cmd.Margin = new Thickness(5);

- Canh lề đúng cho control là một một nghệ thuật bởi vì bạn cần phải xem xét như thế nào lề sẽ
thiết lập các điều khiển lân cận ảnh hưởng đến nhau. Ví dụ, nếu bạn có hai nút chồng lên nhau, và các nút trên cùng có một lề dưới 5 và nút dưới cùng có một đầu biên độ 5, bạn có tổng cộng 10 đơn vị của không gian giữa hai nút. 
Lý tưởng nhất, bạn sẽ có thể để giữ các thiết lập lề khác nhau như phù hợp nhất có thể và tránh thiết lập giá trị riêng biệt cho hai bên lề khác nhau. Ví dụ, trong ví dụ StackPanel nó làm cho cảm giác 
sử dụng đúng khi canh trên của một nút và trên bảng điều khiển chính nó, như ví dụ sau 

?

1

2

3

4

5

6

7

8

"3">

A Button Stack

Cách chuyển đổi giữa các window trong wpf

Cách chuyển đổi giữa các window trong wpf

8. Kích thước tối thiểu , tối đa & kích thước tường minh

- Cuối cùng, tất cả các yếu tố bao gồm thuộc tính Chiều cao và rộng cho phép bạn cung cấp cho các element một kích thước rõ ràng.

- Tuy nhiên, đó không phải là một ý tưởng tốt để thực hiện. Thay vào đó, sử dụng thuộc tính kích thước tối đa Maximum Size và tối thiểu Minimum Size để khóa các element của mình vào phạm vi cho phép, nếu cần.

- Suy nghĩ trước khi thiết lập một kích thước tường minh trong WPF. Trong một bố cục thiết kế tốt, đó là điều không nên làm vì nếu bạn thêm thông tin kích thước tường minh, bạn có nguy cơ tạo ra một bố trí giòn dễ vỡ mà không thể thích ứng với những thay đổi (chẳng hạn như sự khác nhau ngôn ngữ và kích thước cửa sổ) và sẽ cắt cụt nội dung của bạn khi phát sinh những vấn đề kích thước vượt phạm vi cho phép.

- Ví dụ, bạn sẽ quyết định rằng các nút trong StackPanel bạn nên Stretch để phù hợp với
StackPanel nhưng được thực hiện không lớn hơn 200 đơn vị rộng và không nhỏ hơn 100 đơn vị rộng. (Theo mặc định,nút bắt đầu có chiều rộng tối thiểu là 75 đơn vị) Dưới đây là đánh dấu bạn cần:

?

1

2

3

4

5

6

7

8

"3">

A Button Stack

- Tại thời điểm này, bạn có thể tự hỏi " có cách dễ dàng hơn để đặt thuộc tính một cách

chuẩn hóa trên một số thành phần ? " , chẳng hạn như biên nút trong ví dụ này. Câu trả lời là đặc tính Style-một tính năng cho phép bạn sử dụng lại các thiết lập thuộc tính và thậm chí áp dụng một cách tự động luôn sẽ được giới thiệu trong bài viết khác.

- Khi StackPanel xác định kích thước một nút, nó sẽ xem xét một số thông tin:

Kích thước tối thiểu. Mỗi nút phải có kích thước lớn hơn kích thước tối thiểu.

Kích thước tối đa . Mỗi nút sẽ có kích thước luôn luôn nhỏ hơn so với tối đa kích thước ( trừ khi bạn sai khi thiết lập kích thước tối đa là nhỏ hơn kích thước tối thiểu ) .

Nội dung. Nếu content bên trong các nút Button đòi hỏi có chiều rộng lớn hơn,StackPanel sẽ cố gắng để mở rộng nút . ( Bạn có thể tìm ra kích thước của Button bằng cách kiểm tra thuộc tính DesiredSize ,nó sẽ trả về giá trị chiều rộng tối thiểu hoặc chiều rộng nội dung, giá trị lớn hơn )

Kích thước của container. Nếu chiều rộng tối thiểu của nút lớn hơn chiều rộng của StackPanel  , một phần của nút sẽ được cắt bỏ và các nút sẽ không được phép phát triển rộng hơn StackPanel .

Sự liên kết ngang HorizontalAlignment​ . Vì nút sử dụng một HorizontalAlignment có giá trị Stretch mặc định , StackPanel sẽ cố gắng để mở rộng nút để điền vào toàn bộ chiều rộng của StackPanel .


Đó là hướng để hiểu quá trình này và hiểu kích thước tối thiểu và tối đa thiết lập giới hạn tuyệt đối . Trong giới hạn, StackPanel cố gắng tôn trọng kích thước mong muốn của nút ( để phù hợp với nội dung của nút) và các thiết lập liên kết của nó .

?

1

2

3

4

5

6

7

8

"3">

        

            A Button Stack

        

        

        

        

    

- Trong ví dụ này chúng ta chú ý đến thuộc tính MaxWidth="90" thay đổi kích thước của Button 3

Cách chuyển đổi giữa các window trong wpf

Cách chuyển đổi giữa các window trong wpf
Lưu ý : Trong một số trường hợp, bạn có thể muốn sử dụng mã để kiểm tra kích thước của element control trong cửa sổ. Các thuộc tính chiều cao và rộng sẽ không giúp đỡ vì chúng chỉ hiện thực các thiết lập kích thước mong muốn của bạn, mà có thể không tương ứng với kích thước thực tế các control được hiển thị. Và mong muốn của bạn làm cho kích thước của control phù hợp với nội dung của chúng, và 
các thuộc tính Chiều cao và rộng sẽ không được thiết lập ở tất cả. Bạn có thể lấy kích thước thực tế đang được hiển thị bằng cách đọc các thuộc tính ActualHeight và ActualWidth. Nhưng hãy nhớ, những giá trị này có thể thay đổi mỗi khi cửa sổ thay đổi kích cỡ hoặc các nội dung bên trong nó thay đổi.

Thực tế nếu bạn muốn cửa sổ có kích thước tự động thì bạn nên xây dựng một cửa sổ đơn giản với nội dung động. Để cho phép cửa sổ có kích thước tự động, loại bỏ các thuộc tính Chiều cao và rộng 
 và thiết lập thuộc tính Window.SizeToContent = "WidthAndHeight". Cửa sổ sẽ làm cho chính nó chỉ 
đủ lớn để chứa tất cả các nội dung của nó.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

"WPF.View.StackPabeLayout"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="StackPabeLayout" SizeToContent="WidthAndHeight" >

    "3">

        

            A Button Stack

        

        

        

        

    

Cách chuyển đổi giữa các window trong wpf

9.Border

- Border không phải là một panel bố trí, nhưng đó là một phần tử hữu ích mà bạn sẽ thường xuyên sử dụng.Vì lý do đó, nó có ý nghĩa để giới thiệu ngay bây giờ, trước khi bạn đi thêm nữa.
- Lớp Border là sự đơn giản thuần túy cho biết thêm một nền hoặc biên xung quanh c. Để làm chủ Bord, bạn cần biết các thuộc tính được liệt kê sau đây.

Tên thuộc tính Diễn tả chi tiết
- Background  - Thiết lập một nền xuất hiện đằng sau tất cả các nội dung nằm trong
biên bằng cách sử dụng một đối tượng Brush. Bạn có thể sử dụng một solid color.
- BorderBrush và BorderThickness - Thiết lập màu sắc của biên  xuất hiện ở cạnh của Đối tượng Border, sử dụng một đối tượng Brush, và thiết lập chiều rộng của biên, tương ứng. Để hiển thị một biên, bạn phải thiết lập cả hai thuộc tính này.
- CornerRadius - Cho phép bạn nhẹ nhàng làm tròn các góc của biên của bạn.Giá trị càng lớn  của CornerRadius hiệu quả làm tròn sẽ cao hơn.
- Padding - Thêm khoảng cách giữa các biên và nội dung bên trong. (Ngược lại, Margin thêm khoảng cách bên ngoài biên.)

?

1

2

3

4

5

6

7

8

9

"5" Padding="5" Background="LightYellow"

BorderBrush="SteelBlue" BorderThickness="3,5,3,5" CornerRadius="3"

VerticalAlignment="Top">

Cách chuyển đổi giữa các window trong wpf

- Về mặt kỹ thuật, Border là một trang trí, một kiểu phần tử thường được sử dụng để tô điểm đồ họa xung quanh một đối tượng. Tất cả các trang trí xuất phát từ lớp System.Windows.Controls.Decorator
. Hầu hết các trang trí được thiết kế để sử dụng với các điều khiển cụ thể. Ví dụ, các nút sử dụng một ButtonChrome trang trí để có được nhãn hiệu của nó, làm tròn góc và nền bóng mờ, trong khi ListBox sử dụng ListBoxChrome trang trí. Ngoài ra còn có hơn hai trang trí chung rất hữu ích khi soạn giao diện người dùng: Border thảo luận ở đây và ViewBox.

10.Wrapper Panel

- WrapPanel cho phép sắp xếp các phần tử từ trái sang phải. Khi một dòng phần tử đã điền đầy khoảng không gian cho phép theo chiều ngang, WrapPanel sẽ cuốn phần tử tiếp theo xuống đầu dòng tiếp theo

?

1

2

3

4

5

6

7

8

9

10

11

12

13

"WPF.View.StackPabeLayout"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="StackPabeLayout" Height="200" Width="300" >

        

    "Beige">

        "14" Foreground="#58290A"> Chú cào cào nhỏ, ngồi trong đám cỏ

        

        "#feca00" BorderThickness="2">

            Control 3

        

    

- Do chiều dài tổng cộng của 3 control lớn hơn chiều dài của Window, đồng thời, chiều dài của 2 control đầu (TextBlock và Button) nhỏ hơn chiều dài Window, WrapPanel sẽ xếp TextBlock cuối cùng xuống hàng dưới. Kết quả là:

Cách chuyển đổi giữa các window trong wpf

11.Dock Panel

- DockPanel cho phép các phần tử bám lên các cạnh của panel DockPanel bao chứa chúng, tương tự như khái niệm Docking trong Windows Forms. Nếu như có nhiều phần tử cùng bám về một cạnh, chúng sẽ tuân theo thứ tự mà chúng được khai báo trong file XAML. Sau đây là đoạn mã XAML minh họa việc sử dụng DockPanel:

?

1

2

3

4

5

6

7

8

9

10

        "16" DockPanel.Dock="Top"

        Foreground="#58290A"> Control 1

        

        

        

        "#feca00" BorderThickness="2">

            Control 5

        

Cách chuyển đổi giữa các window trong wpf

- Sử dụng thuộc tính LastChildFill="True"

?

1

2

3

4

5

6

7

8

9

10

11

"True">

        

        

        

        

        

        

        

Cách chuyển đổi giữa các window trong wpf

12. Bố cục lồng nhau của các Panel

- StackPanel, WrapPanel, và DockPanel ít được sử dụng riêng lẻ. Thay vào đó, chúng được kết hợp và lồng nhau để định hình phần của giao diện của bạn. Ví dụ, bạn có thể sử dụng một DockPanel để đặt StackPanel khác nhau và StackPanel chứa WrapPanel trong các khu vực thích hợp của một cửa sổ.
- Ví dụ, hãy tưởng tượng bạn muốn tạo ra một hộp thoại dialog tiêu chuẩn với một nút OK và Cancel ở
góc dưới bên phải và một vùng lớn nội dung trong phần còn lại của cửa sổ. Bạn có thể mô hình hóa giao diện này với WPF với nhiều cách khác nhau, nhưng sự lựa chọn dễ dàng nhất qua những gì chúng ta đã học là sử dụng các panel bạn đã biết cho đến nay là như sau:

1. Tạo ra một StackPanel ngang để bọc các nút OK và Cancel với nhau.
2. Đặt StackPanel này vào trong một DockPanel và thiết lập để cho nó bám vào cạnh phía dưới của cửa sổ.
3. Thiết lập thuộc tính DockPanel.LastChildFill là true, do đó bạn có thể sử dụng phần còn lại của cửa sổ để điền vào nội dung khác. Bạn có thể thêm một điều khiển bố cục ở đây hoặc chỉ là một TextBox (như trong ví dụ này).
4. Thiết lập các thuộc tính lề để cung cấp cho đủ lượng khoảng trống cần thiết.

?

1

2

3

4

5

6

7

8

"True">

        "Bottom" HorizontalAlignment="Right"

        Orientation="Horizontal">

            

            

        

        "Top" Margin="10">This is a test.

Cách chuyển đổi giữa các window trong wpf

Cách chuyển đổi giữa các window trong wpf
Lưu ý : Nếu bạn có một tree có mật độ lồng nhau các phần tử, sẽ dễ dàng để mất tầm nhìn của cấu trúc tổng thể. Visual Studio cung cấp một tính năng tiện dụng mà cho bạn thấy một cây đại diện các phần tử của bạn và cho phép bạn nhấp vào theo cách của bạn xuống phần tử bạn muốn xem (hoặc sửa đổi). Tính năng này là cửa sổ Document Outline, và bạn có thể hiển thị nó bằng cách chọn View ➤ Other Windows ➤ Document Outline từ trình đơn menu.

13. Grid

- Panel dạng Grid là dạng panel hết sức linh hoạt, và có thể sử dụng để đạt được gần như tất cả khả năng mà các dạng panel khác có thể làm được, mặc dù mức độ khó dễ không giống nhau. Grid cho phép ta phân định các dòng và cột theo dạng một lưới kẻ ô, và sau đó sẽ sắp đặt các phần tử UI vào các ô tùy ý. Grid sẽ tự động chia đều các dòng và cột (dựa trên kích thước của phần nội dung). Tuy nhiên, ta có thể sử dụng dấu sao (*) để phân định kích thước theo tỉ lệ hoặc phân định giá trị tuyệt đối về chiều cao hoặc chiều rộng cho hàng và cột. Ta có thể nhận biết sự khác biệt của 2 dạng phân định kích thước nêu trên bằng cách thay đổi kích thước của form chứa panel Grid. Thêm vào đó, thuộc tính ShowGridLines được đặt bằng True cho phép hiển thị các đường kẻ ô. Sau đây là một ví dụ minh họa về việc sử dụng Grid với hai dạng phân định:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

    "10" ShowGridLines="True">

        

        

            

            "2*" />

            

            

        

        

        

            

            "25" />

            

            

            

            "2*"/>

        

        

        "16" Foreground="#58290A"

            Grid.Column="0" Grid.Row="0"> Chú cào cào nhỏ

        

        

        

        "#feca00" BorderThickness="2"

                Grid.Column="1" Grid.Row="2">

            Control 3

        

    

Cách chuyển đổi giữa các window trong wpf

Cách chuyển đổi giữa các window trong wpf
Lưu ý : Grid phù hợp với các bố cục mà các phần tử dạng hàng và cột xác định trước. Điều này khác với các container bố cục như WrapPanel và StackPanel là tạo ra các hàng hoặc cột tiềm ẩn khi chúng nằm chờ hiện phần tử con của chúng. 

Nếu bạn muốn tạo ra lưới có nhiều hơn một dòng và một cột, bạn phải xác định hàng và cột bằng cách khai báo rõ ràng RowDefinition và ColumnDefinition.

- Bây giờ chúng ta thay đổi kích thước của cửa sổ chứa Grid trong ví dụ trên để tìm hiểu thêm về bố cục của Grid đôi chút

Cách chuyển đổi giữa các window trong wpf

- Khi kích thước form chứa Grid thay đổi, chiều cao của hàng 1 luôn cố định (25pixel), trong khi đó, chiều cao của hàng 2 luôn gấp đôi hàng 1; chiều rộng của cột 0 luôn gấp đôi chiều rộng của cột 1 đó chính là điều chúng ta cần quan tâm với Grid và để hiểu rõ hơn về Grid

13.1 Tinh chỉnh hàng và cột

- Nếu lưới chỉ đơn giản là một lưới kích thước của hàng và cột là cố định, nó sẽ không có gì đặc biệt. May mắn thay, nó không phải như vậy. Để mở khóa tiềm năng đầy đủ của Grid, bạn có thể thay đổi kích thước của mỗi hàng và cột. 
Grid hỗ trợ ba kiểu kích thước:

+ Kích thước tuyệt đối Absolute Size: Bạn sẽ chọn kích thước chính xác cho các element control nằm trong grid. Đây là cách không hữu ích nhất vì nó không đủ linh hoạt để đối phó với thay đổi 
kích thước nội dung, thay đổi kích thước container, hoặc sự hỗ trợ thay đổi của đa ngôn ngữ.

+  Kích thước tự động Automatic Size :  Mỗi hàng hoặc cột được đưa ra chính xác số không gian nó 
cần, và không hơn cho các element control nằm trong nó. Đây là một trong các phương pháp kích thước hữu ích nhất. 

+ Kích thước theo tỷ lệ Proportinal Size :  Không gian được phân chia giữa một nhóm các hàng hoặc cột. Đây là kiểu tiêu chuẩn cho tất cả các hàng và cột.

- Để đạt được linh hoạt tối đa, bạn có thể trộn và kết hợp các kiểu kích thước khác nhau điều đó
thường hữu ích để tạo ra nhiều hàng tự động có kích thước và sau đó để một hoặc hai hàng còn lại có được không gian còn sót lại qua kích thước theo tỷ lệ.Bạn thiết lập các hình thức kích thước bằng cách sử dụng thuộc tính Width của đối tượng ColumnDefinition hoặc thuộc tính Height của đối tượng RowDefinition với một giá trị. Ví dụ, đây là cách bạn thiết lập một chiều rộng tuyệt đối 100 pixel:

?

1

"100">

- Sử dụng kích thước tự động, bạn sử dụng một giá trị của Auto:

?

1

"Auto">

- Cuối cùng, sử dụng kích thước theo tỷ lệ, bạn sử dụng dấu sao (*):

?

1

"*">

- Cú pháp này xuất phát từ thế giới lập trình Web, nơi nó được sử dụng với các trang frame HTML. Nếu bạn kết hợp các kích thước tỷ lệ và chế độ kích thước khác, các hàng hoặc cột tương ứng có kích thước nhận được không gian còn sót lại.Nếu bạn muốn chia không gian còn lại không đồng đều, bạn có thể chỉ định một giá trị cho hàng và cột, mà bạn phải trước hàng hay cột bạn thiết lập dấu hoa thị. Ví dụ, nếu bạn có hai hàng tương ứng có kích thước và bạn muốn là dòng đầu tiên được một nửa chiều cao dòng thứ hai, bạn có thể chia sẻ không gian còn lại như thế này:

?

1

2

"*">

"2*">

- Sử dụng các kiểu kích thước, bạn có thể lặp lại trong các ví dụ hộp thoại đơn giản ở phần DockPanel 
sử dụng một lưới chứa để phân chia các cửa sổ thành hai hàng, chứ không phải là một DockPanel. Đây là đánh dấu bạn cần:

?

1

2

3

4

5

6

7

8

9

10

11

12

"True">

"*">

"Auto">

"10" Grid.Row="0">This is a test.

"1" HorizontalAlignment="Right"

    Orientation="Horizontal">

Cách chuyển đổi giữa các window trong wpf

13.2 Span Row & Column

- Bạn đã thấy cách đặt control trong ô của Grid bằng cách sử dụng Row và Column bạn cũng có thể sử dụng hai thuộc tính khác để làm cho strecth phần tử trên một số ô: RowSpan và ColumnSpan. Giá trị của các thuộc tính này xác định các hàng hoặc cột mà control element sẽ chiếm.Ví dụ sau , Button sẽ chiếm không gian của ô đầu tiên và ô thứ 2 của dòng đầu tiên :

?

1

- Và nút này sẽ Strecth nhiều hơn bốn tế bào trong tổng số bằng Span hai cột và hai hàng:

?

1

2

- Đánh dấu hoàn chỉnh để hiểu rõ về ColumnSpan và RowSpan

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

"True">

        

            "*">

            "Auto">

        

        

            "*">

            "Auto">

            "Auto">

        

        "10" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">

            This is a test.

        

        

     


14.Split Window :

- Mỗi người sử dụng Windows đã nhìn thấy ngăn splitter thanh-kéo tách biệt một cửa sổ thành các vùng khác nhau. Ví dụ, khi bạn sử dụng Windows Explorer, bạn đang trình bày một danh sách các thư mục (trên bên trái) và một danh sách các tập tin (bên phải). Bạn có thể kéo thanh splitter ở giữa để xác định tỷ lệ cho 2 vùng trên cửa sổ.
- Trong WPF, thanh splitter được đại diện bởi lớp GridSplitter và là một tính năng của Grid bằng cách thêm một GridSplitter cho một Grid, bạn cung cấp cho người dùng khả năng thay đổi kích thước hàng hoặc cột.

- Có một số nguyên tắc khi sử dụng GridSplitter :

+ Các GridSplitter phải được đặt trong một tế bào lưới của Grid. Một cách tiếp cận tốt là nên đặt cột chuyên dụng hoặc hàng cho các GridSplitter, với giá trị của Height | Width là Auto.

+ Các GridSplitter luôn luôn thay đổi kích thước toàn bộ hàng hoặc cột để thực hiện sự xuất hiện của GridSplitter phù hợp với hành vi mong muốn, bạn nên gán Strecth cho GridSplitter trên toàn bộ một hàng hoặc cột, chứ không phải là giới hạn trong một ô đơn lẻ. Để thực hiện điều này, bạn sử dụng các thuộc tính Rowspan hoặc ColumnSpan

+ Ban đầu, GridSplitter là vô hình. Để làm cho nó có thể sử dụng, bạn cần phải cung cấp cho nó một kích thước tối thiểu. Trong trường hợp của một thanh splitter thẳng đứng, bạn cần phải thiết lập VerticalAlignment Stretch (để lấp đầy toàn bộ chiều cao) và Width với một kích thước cố định (ví dụ như 10 pixel). Trong trường hợp của một thanh splitter ngang, bạn cần phải thiết lập HorizontalAlignment Strecth và thiết lập Height với một kích thước cố định.

+ Sự canh lề GridSplitter cũng xác định xem thanh splitter là nằm ngang (sử dụng để thay đổi kích thước hàng) hay thẳng đứng (được sử dụng thay đổi kích thước cột). Trong trường hợp của một
thanh splitter ngang, bạn nên đặt VerticalAlignment Center (đó là giá trị mặc định) để chỉ ra rằng kéo vạch ngăn cách thay đổi kích thước các hàng ở trên và dưới đây. Trong trường hợp của một thanh splitter thẳng đứng, bạn nên đặt HorizontalAlignment Center thay đổi kích thước các cột ở hai bên.

Cách chuyển đổi giữa các window trong wpf
Lưu ý : Bạn có thể thay đổi hành vi thay đổi kích thước bằng cách sử dụng các thuộc tínhResizeDirection và ResizeBehavior của GridSplitter

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

"100">

"Auto">

"50">

"0" Grid.Column="1" Grid.RowSpan="2"

Width="3" VerticalAlignment="Stretch" HorizontalAlignment="Center"

ShowsPreview="False">

Cách chuyển đổi giữa các window trong wpf

- Đánh dấu này có một chi tiết bổ sung mà chúng ta nên tìm hiểu. Khi GridSplitter được khai báo, thuộc tính ShowsPreview được thiết lập là false. Kết quả là, khi thanh splitter được kéo về phía khác, các cột thay đổi kích cỡ ngay lập tức. Nhưng nếu bạn thiết lập ShowsPreview là true, khi bạn kéo, bạn sẽ thấy một cái bóng màu xám theo con trỏ chuột hiển thị cho bạn nơi split sẽ di chuyển đến. Các cột sẽ không được thay đổi kích cỡ cho đến khi bạn thả chuột nút. Bạn cũng có thể sử dụng các phím mũi tên để thay đổi kích thước một GridSplitter một khi nó nhận được focus. Ngoài ShowsPreview bạn cũng có thể điều chỉnh thuộc tính DragIncrement nếu bạn muốn ép buộc splitter để di chuyển một lúc nhiều đơn vị chẳng hạn như 10 pixel tại mỗi di chuyển. Nếu bạn muốn kiểm soát các kích thước cho phép tối đa và tối thiểu của các cột, bạn chỉ cần đảm bảo các thuộc tính thích hợp được thiết lập trong phần ColumnDefinitions.