Học WPF 4 trong một tuần – Ngày thứ 3: Layout and Controls

images

Hôm nay chúng ta sẽ bắt đầu ngày thứ 3 với nhiều hứng thú hơn trong ngày thứ 2 với WPF 4. Open-mouthed smile

Hôm nay chúng ta sẽ tìm hiểu về những cách bố trí (layout) cơ bản, các hành động với grid layout panel, các phần tử stack, stackpanel, một cái nhìn tổng quan về sự đa dạng của các control, và thư viện hỗ trợ của bên thứ 3.

1. Tìm hiểu về các cách bố trí cơ bản (Learn the layout basics)

1.1 Tại sao bố trí là rất quan trọng? (Why layout is so important?)

– Cách bố trí của các control là quan trọng đối với khả năng sử dụng các ứng dụng. Sắp xếp các control dựa trên dựa trên các điểm ảnh có tọa độ cố định có thể làm cho môi trường làm việc trở nên hạn chế. Nhưng ngay khi bạn muốn sử dụng nó các độ phân giải màn hình khác nhau hay với kích thước font  khác nhau nó sẽ không thể hiển thị được. WPF cung cấp một tập hợp phong phú được xây dựng trong các bảng bố trí (layout panels) giúp bạn tránh những cạm bẫy phổ biến trong hiển thị.

– Dưới đây là 5 bảng bố trí phổ biến nhất trong WPF:

1.2 Những thực tiễn tốt (Best Practices)

– Tránh cố định các vị trí – sử dụng các thuộc tính như Alignment kết hợp với Margin để vị trí các phần tử trong panel.

– Tránh cố định các kích thước – Thiết lập thuộc tính Width và Height của các phần tử là Auto bất cứ khi nào có thể.

– Đừng lạm dụng canvas panel để bố trí các phần tử. Chỉ sử dụng nó cho đồ họa vector.

– Sử dụng các StackPanel cho các bố trí (layout) của một hộp thoại (dialog).

– Sử dụng GridPanel để bố trí một hình thức nhập dữ liệu tĩnh. Tạo một cột cột tự động điều chỉnh kích thước cho label và một cột Star sized cho các Textbox.

– Sử dụng một ItemControl với một Grid panel trong một DataTemplate để bố trí năng động các khóa giá trị trong các danh sách. Sử dụng SharedSize để đồng bộ hóa độ rộng các nhãn (label).

1.3 Liên kết dọc và ngang (Vertical and Horizontal Alignment)

Sử dụng các thuộc tính VerticalAligment và HorizontalAligment để neo (dock) các control cho một hoặc nhiều mặt bảng (panel). Hình ảnh dưới đây minh họa cách xử lý với kích thước với các tập hợp khác nhau.

image

1.4 Margin và Padding

Các thuộc tính Margin và Padding có thể được sử dụng để lưu trữ một số không gian xung quanh của control.

– Margin là không gian thêm xung quan của control.

– Padding là không gian thêm bên trong của control.

– Padding của một điều khiển bên ngoài, còn Margin là một điều khiển bên trong.

image

1.5 Chiều cao và chiều rộng (Height and Width):

Mặc dù không phải là một điều bắt buộc, tất cả các control phải cung cấp các thuộc tính chiều cao (height) và chiều rộng (width) cho một phần tử có kích thước cố định. Cách tốt nhất là sử dụng các thuộc tính MinHeight, MaxHeight, MinWidth và MaxWidth để xác nhận phạm vi chấp nhận được.

Nếu bạn thiết lập chiều rộng hoặc chiều cao tự động điều khiển thì kích thước của nó sẽ tương ứng với kích thước của nội dung.

1.6 Xử lý tràn (Overflow Handing)

Các layout panel thường cắt những phần mà các phần tử con của nó chồng lên biên giới của panel. Hành vi này có thể được kiểm soát bằng cách thiết lập thuộc tính ClipToBounds là true hay false.

image

1.7  Cuộn( scrolling)

Khi nội dung quá lớn để phù hợp với kích thước có sẵn, bạn có thể cuộn nó vào một ScrollViewer. ScrollViewer sử dụng 2 thanh cuộn để  lựa chọn vùng hiển thị.

Các khả năng hiển thị của thanh cuộn có thể được điều khiển ngang dọc bằng thuộc tính ScrollbarVisibility.

<ScrollViewer>
     <StackPanel>
           <Button Content="First Item" />
                       <Button Content="Second Item" />
          <Button Content="Third Item" />
      </StackPanel>
 </ScrollViewer>

2. Grid panel

2.1 Giới thiệu (introduction)

image

Grid là một layout panel(bảng bố trí) sắp xếp các control con của nó trong một cấu trúc dạng bảng gồm các hàn(rows) và cột (columns). Chức năng của nó tương tự table trong HTML, nhưng linh hoạt hơn. Một ô (cell) có thể chứa nhiều các control, chúng có thể lan qua nhiều ô và thậm chí có thể chồng lên nhau.

Các hành vi thay đổi kích thước của các control được xác định bởi các thuộc tính HorizontalAlignment và VerticalAlignment xác định các điểm neo (anchors). Khoảng cách giữa các neo (anchors) và các Grid line được quy định được quy định bằng trong thuộc tính margin(canh lề) của control.

2.2 Xác định các dòng và cột (Define Rows and Columns)

Theo mặc định thì Grid có một hàng và một cột. Để tạo thêm các hàng và cột, bạn phải thêm các mục RowDefinition vào RowDefinitions collection và các mục ComlumnDefiniton vào ColumnDefintions collection. Ví dụ sau đây minh họa việc tạo một grid với 3 hàng và 2 cột.

Kích thước này có thể được quy định như một số lượng tuyệt đối của các đơn vị hợp lý (logical units), như một giá trị phần trăm hoặc tự động.

– Cố định (Fixed): cố định kích thước của các logical unit (1/96 inch).

– Tự động (Auto): Có không gian càng nhiều đủ để chứa các control.

– Sao (Star “*”): Có nhiều không gian khả dụng, phần trăm được chia cho tất cả các ô cỡ sao(star-sized) . Star-sized giống như tỉ lệ phần trăm, ngoại trừ tổng của tất cả các cột star không phải là 100%. Hãy nhớ rằng Star-sizing sẽ không làm việc nếu kích thước Grid được tính toán dựa trên nội dung của nó.


<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="28" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
</Grid>

2.3. Làm thế nào để thêm controls vào Grid (How to add controls to grid?)

Để thêm các control và grid chúng ta chỉ cần đặt thêm các khai báo giữa thẻ mở và thẻ đóng của grid. Hãy nhớ rằng, các định nghĩa hàng và cột phải đứng trước bất kỳ định nghĩa của các control con.

Grid layout panel cung cấp 2 thuộc tính Grid.Column và Grid.Row để xác định vị trí của control.


<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="28" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="200" />
    </Grid.ColumnDefinitions>
    <Label Grid.Row="0" Grid.Column="0" Content="Name:"/>
    <Label Grid.Row="1" Grid.Column="0" Content="E-Mail:"/>
    <Label Grid.Row="2" Grid.Column="0" Content="Comment:"/>
    <TextBox Grid.Column="1" Grid.Row="0" Margin="3" />
    <TextBox Grid.Column="1" Grid.Row="1" Margin="3" />
    <TextBox Grid.Column="1" Grid.Row="2" Margin="3" />
    <Button Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right" 
            MinWidth="80" Margin="3" Content="Send"  />
</Grid>

2.4 Thay đổi kích thước của các cột hoặc hàng (Resizable Columns or Rows)

image

WPF cung cấp một control được gọi là GridSpitter, control này được thêm vào bất kỳ control khác trong một ô (cell) của grid. Điều đặc biệt ở đây chính là lấy gridline gần nhất để thay đổi chiểu rộng hoặc chiều cao của nó khi kéo control xung quanh.

 


<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Label Content="Left" Grid.Column="0" />
    <GridSplitter HorizontalAlignment="Right" 
                  VerticalAlignment="Stretch" 
                  Grid.Column="1" ResizeBehavior="PreviousAndNext"
                  Width="5" Background="#FFBCBCBC"/>
    <Label Content="Right" Grid.Column="2" />
</Grid>

Cách tốt nhất để gắn một gridsplitter là đặt trong cột tự động thay đổi kích thước của chính nó. Làm theo cách này ngăn cản được sự chồng chéo với các ô lân cận. Để đảm bảo rằng gridsplitter thay đổi kích thước ô trước và sau bạn phải thiết lập ResizeBehavior thành PreviousAndNext.

Splitter thông thường nhận ra hướng thay đổi kích thước theo tỷ lệ giữa chiều cao và chiều rộng của nó. Nhưng nếu bạn thích, bạn cũng có thể thiết lập ResizeDirection thành Columns hay Rows.

<GridSplitter ResizeDirection="Columns"/>

2.5  Làm thế nào để chia sẽ chiều rộng của một cột trên nhiều grid (How to share the width of column over multiple grids?)

– Các kích thước được chia sẽ của grid layout cho phép nó đồng bộ hóa với chiều rộng của cột trên nhiều grid. Tính năng này rất hữu ích nếu bạn muốn thực hiện một listview với nhiều cột bằng cách sử dụng một grid như layout panel với dữ liệu mẫu. Bởi vì mỗi một item chứa trong grid riêng của mình, các cột sẽ có chiều rộng không giống nhau.

– Bằng cách thiết lập thuộc tính Grid.IsSharedSizeScope là true và một parent element bạn có thể xác định được phạm vi trong độ rộng cột được chia sẽ.

– Để đồng bộ được chiều rộng của 2 columndefinition, bạn tiến hành thiết lập ShareSizeGroup cùng tên


<ItemsControl Grid.IsSharedSizeScope="True" >
  <ItemsControl.ItemTemplate> 
    <DataTemplate>
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition SharedSizeGroup="FirstColumn" Width="Auto"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="{Binding Path=Key}" TextWrapping="Wrap"/>
        <TextBlock Text="{Binding Path=Value}" Grid.Column="1" TextWrapping="Wrap"/>
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

2.6  Những gợi ý hữu ích (Useful Hints)

Các cột và các hàng tham gia chia sẽ có kích thước không xác định trong star-sizing. Trong kịch bản size-sharing, Star-sizing được coi là tự động. Từ TexWrapping trên Texblock trong một cột SharedSize không làm việc, bạn có thể loại trừ cột cuối cùng của bạn từ các kích thước được chia sẽ, điều này sẽ giúp giải quyết vấn đề.

2.7  Sử dụng Gridlengths từ mã lệnh (Using GridLengths from code)

Nếu bạn muốn thêm các cột hay hàng bằng code, bạn có thể sử dụng lớp GridLength để định nghĩa các kiểu kích thước khác nhau.

Auto sized GridLength.Auto

Star sized new GridLength(1,GridUnitType.Star)

Fixed size new GridLength(100,GridUnitType.Pixel)

Grid grid = new Grid();

ColumnDefinition col1 = new ColumnDefinition();
col1.Width = GridLength.Auto;
ColumnDefinition col2 = new ColumnDefinition();
col2.Width = new GridLength(1,GridUnitType.Star);

grid.ColumnDefinitions.Add(col1);
grid.ColumnDefinitions.Add(col2);

3. WPF StackPanel

image

3.1 Giới thiệu (introduction)

StackPanel  WPF là đơn giản và hữu ích trong layout panel. Nó ngăn xếp cách thành phần con của của nó bên dưới hoặc bên cạnh nhau, phụ thuộc vào hướng của nó. Điều này rất hữu ích để tạo ra bất các loại danh sách. Tất cả các WPF ItemControls giống như ComboBox, ListBox hoặc Menu sử dụng StackPanel như một layout panel chung.

 


<StackPanel>
  <TextBlock Margin="10" FontSize="20">How do you like your coffee?</TextBlock>
  <Button Margin="10">Black</Button>
  <Button Margin="10">With milk</Button>
  <Button Margin="10">Latte machiato</Button>
  <Button Margin="10">Chappuchino</Button>
</StackPanel>

3.2 Stack Items Horizontally

Một ví dụ hay cho một Horizontal stack panel  là button “Ok”  và “Cancel”  của một hộp thoại Windows. Bởi vì kích thước của văn bản có thể thay đổi font-size hoặc chuyển đổi các ngôn ngữ, do đó chúng ta nên tránh cố định kích thước của button. Stack panel xếp thẳng hàng 2 button tùy thuộc vào mong muốn của chúng. Nếu chúng cần nhiều không gian hơn, chúng sẽ nhận nó một cách tự động. Không bao giờ trộn lẫn lại với button nhỏ và button quá lớn.

image


<StackPanel Margin="8" Orientation="Horizontal">            
   <Button MinWidth="93">OK</Button>
   <Button MinWidth="93" Margin="10,0,0,0">Cancel</Button>
</StackPanel>

4. Tích hợp các controls của WPF (Built-in Controls of  WPF)

WPF cung cấp một tập hợp phong phú các tập hợp control. Các control có thể được phân chia thành các loại sau đây:

Third Party Controls

DataGrid

ItemsControl

LivePreview ComboBox

Dialogs

Slider

Popup

RadioButton

ToolTips

TextBox

Menus

Expander

PasswordBox

ContextMenu

Calendar

ListBox

ListView

Window

5. Các control của bên thứ 3 (WPF – Third party Controls)

Dưới đây là các thư viện hỗ trợ thiết kế giao diện WPF của các hãng nổi tiếng, các bạn có thể tham khảo thêm khi thiết kế phần mềm.

WPF component vendors

Misc

Outlook Bar

Panels

Reporting

Ribbon

Toolbar

Theming

Tree

Schedule

3D

Web Browser

Advertisements

About thanhcuong1990

Handsome and talent!! ^^
This entry was posted in WPF. Bookmark the permalink.

4 Responses to Học WPF 4 trong một tuần – Ngày thứ 3: Layout and Controls

  1. acumen says:

    Xin chào a Cường, e xin có 1 chút góp ý về phần GridSpliter.
    E nghĩ a nên thêm vào MinWidth cho mỗi column trong Grid Panel, ví dụ như giả sử e có 1 grid panel có 3 column trong đó column 1 và 3 dc gán 1 đoạn text là left và right, còn column 2 là gridspliter.
    Nếu làm như a ở trên mà ko khai báo MinWidth cho column 1 và 3 thì khi kéo lố GridSpliter về 1 bên, giả sử kéo về bên trái thì sẽ có nguy cơ column 1 sẽ biến mất.

    • Chào em!
      Ý kiến của em cũng khá hay. Việc sử dụng các control trong WPF khá đa dạng và tùy theo nhu cầu mà mỗi người có thể tạo ra cho mình một control riêng bằng cách kết hợp các control sẵn có. Cảm ơn em đã quan tâm.

  2. suphamtink34 says:

    Em chào các anh!
    Các anh cho em hỏi làm sao mình có thể liên kết các window với nhau?
    Ví dụ nhấp một button sẽ ra một window khác

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s