WPF – Element Tree: Logical Tree và Visual Tree

Một giao diện người dùng trong WPF có thể được tổ chức thành một cấu trúc cây để thể hiện mối quan hệ giữa các thành phần tạo nên chúng. Cấu trúc cây này được tổ chức tương tự như một tài liệu XAML mà bạn thiết kế và được gọi là Element Tree. Element Tree được phân ra thành Logical Tree và Visual Tree.

Logical Tree

Cấu trúc của Logical Tree bao gồm các thành phần của cửa sổ trong lúc runtime và gần với cấu trúc tài liệu XAML mà bạn thiết kế. Logical Tree sẽ được dùng để thực hiện tính năng value inheritance của các dependency property và các tính năng về event, resource,…

Ví dụ với tài liệu XAML sau:

<Window x:Class="Wpf1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF - Element Tree Viewer" Height="300" Width="300">
    <DockPanel>
        <StackPanel>
            <Button>Logical Tree</Button>
            <Button >Visual Tree</Button>
        </StackPanel>
        <TreeView/>
    </DockPanel>
</Window>

Logical Tree tương ứng sẽ là:

Duyệt Logical Tree

Lớp LogicalTreeHelper chứa các static method cho phép bạn duyệt qua các thành phần của Logical Tree. Tôi sẽ dùng phương thức  GetChildren() để lấy về tất cả con của một thành phần thuộc Logical Tree. Bởi vì Logical Tree có thể chứa bất kì kiểu dữ liệu nào, ta cần truyền một tham số kiểu object để đại diện cho thành phần hiện tại đang được duyệt:

void DumpLogicalTree(TreeViewItem parentNode,object element)
{
    TreeViewItem item=new TreeViewItem();
    item.Header=": "+element.ToString();
    parentNode.Items.Add(item);

    DependencyObject deObj = element as DependencyObject;

    if(deObj!=null)
        foreach(var child in LogicalTreeHelper.GetChildren(deObj))
            DumpLogicalTree(item,child);
}

Visual Tree

Visual Tree là cấu trúc cây mở rộng ra từ Logical Tree và chứa tất cả thành phần trực quan trên giao diện được vẽ ra thiết bị xuất (thông thường là màn hình). Các thành phần này dùng để hiện thực các đặc tính về hiển thị, hit-testing, layout,…

Các thành phần trong Visual Tree được kế thừa từ  Visual hoặc Visual3D. Visual Tree không bao gồm các tất cả thành phần có trong Logical Tree, ví dụ như String trong Logical Tree được chuyển thành một TextBlock trong Visual Tree.

Khi cần vẽ ra thiết bị xuất, cấu trúc cây này sẽ thể hiện thứ tự các phần tử được duyệt ra để lấy thông tin vẽ, bắt đầu từ phần tử gốc cho tới khi duyệt qua hết các phần tử con trong Visual Tree.

Vẫn với tài liệu XAML trong phần trên, Visual Tree sẽ có dạng sau (các node màu đỏ là các thành phần thuộc Logical Tree):

Duyệt Visual Tree

Lớp VisualTreeHelper không cung cấp phương thức để trả về một tập hợp các thành phần con, thay vào đó ta đếm tất cả thành phần con bằng GetChildrenCount(), và dùng GetChild() để lấy về thành phần con với chỉ số được xác định.

void DumpVisualTree(TreeViewItem parentNode, DependencyObject element)
{
    TreeViewItem item=new TreeViewItem();
    item.Header=": "+element.ToString();
    parentNode.Items.Add(item);

    int count = VisualTreeHelper.GetChildrenCount(element);

    for (int i = 0; i < count; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(element, i);
        DumpVisualTree(item,child);
    }
}

Chương trình xem Element Tree

Chương trình minh họa sẽ hiển thị Logical Tree và Visual Tree dựa vào thông tin lấy từ chính cửa sổ của nó lên một TreeView. Bạn lần lượt nhấn hai button tương ứng để xem các Element Tree được tạo ra.

Download sourcecode+demo (9KB) (open new tab)

https://yinyangit.wordpress.com

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s