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
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ó
- Ngoài các container chính chúng ta còn có 1 số container phụ chẳng hạn như TabPanel 4.Tạo một bố cục đơn giản với Stack Panel Code XAML ?
4.1 Sắp xếp theo chiều ngang ?
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 :
- 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 - 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 đó : ?
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: ?
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 ?
- 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 ?
- 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ẽ ?
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 ?
- 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 .
?
- 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 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 ?
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.
?
- 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 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 ?
- 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à: 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: ?
- Sử dụng thuộc tính LastChildFill="True" ?
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ổ. 1. Tạo ra một StackPanel ngang để bọc các nút OK và Cancel với nhau. ?
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: ?
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 - 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. + 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 tự động Automatic Size : Mỗi hàng hoặc cột được đưa ra chính xác số
không gian nó + 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 đó ?
- Sử dụng kích thước tự động, bạn sử dụng một giá trị của Auto: ?
- Cuối cùng, sử dụng kích thước theo tỷ lệ, bạn sử dụng dấu sao (*): ?
- 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: ?
- 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 ?
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 : ?
- 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: ?
- Đánh dấu hoàn chỉnh để hiểu rõ về ColumnSpan và RowSpan ?
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ổ. - 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 ?
- Đá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. |