Thứ hai, ngày 5 tháng 12 năm 2016

WPF – Tìm hiểu về Dependency Property

Ngày đăng: 20/3/2012, 8:43:32AM | Lượt xem: 3,042
Hot!

Khác với các property mà bạn thường sử dụng trong .NET (CLR Property), WPF sử dụng một kiểu property mới được gọi là Dependency Property. Trong bài tôi sẽ giới thiệu các kiến thức cơ bản về Dependency Property và cách tạo một Dependency Property đơn giản.

 

Khác với các property mà bạn thường sử dụng trong .NET (CLR Property), WPF sử dụng một kiểu property mới được gọi là Dependency Property. Trong bài tôi sẽ giới thiệu các kiến thức cơ bản về Dependency Property và cách tạo một Dependency Property đơn giản.

 

CLR Property và Dependency Property

CLR property được hiện thực bằng cách sử dụng một private field và một “wrapper” (get, set) để lưu trữ và truy xuất giá trị. Trong khi đó, dependency property lưu trữ các giá trị trong một dictionary gồm các dòng dữ liệu dạng key/value, với key là tên của property và value là giá trị lưu trữ.

Lợi ích của dependency property là không phải tốn bộ nhớ lưu trữ các private field mà đa số chúng chỉ mang giá trị mặc định. Dependency property chỉ chỉ lưu trữ các giá trị bị thay đổi. Các giá trị mặc định của kiểu dữ liệu được lấy từ Dependency Property Metadata. Một số giá trị mặc định mặc định của các kiểu dữ liệu khi bạn tạo dependency property:

-          Kiểu tham chiếu (bao gồm string): null

-          Kiểu structure: dựa vào default constructor

-          Kiểu số: zero

Trong trường hợp phần tử hiện tại không chứa giá trị của property cần lấy, dependency property sẽ duyệt lên các phần tử ở mức cao hơn để tìm giá trị (ví dụ Button > Grid > Window).  Ví dụ như khi bạn gán FontSize cho Window, các thành phần con của nó cũng được áp dụng giá trị FontSize này, tính năng này được gọi là Value Inheritance.

Khi một dependency property được đăng ký, bạn có thể chỉ định các phương thức callback xử lý trong trường hợp giá trị của chúng bị thay đổi. Ngoài ra, dependency property liên quan mật thiết đến những tính năng của WPF như resource, style, animation, data binding,….

Sử dụng Dependency Property

Các dependency property có thể được truy xuất trực tiếp thông qua tên của chúng trong tài liệu XAML. Trong code-behind, chúng được truy xuất thông qua hai phương thức GetValue() và SetValue(). Để thuận tiện, bạn nên tạo một wrapper giống như CLR property.

Trong XAML:

Với kiểu dữ liệu đơn giản, bạn có thể gán trực tiếp như các attribute của thẻ, như property Width sau:

<Button Width=”100″>Button1</Button>

Tuy nhiên bạn cũng có thể dùng cú pháp khác, sử dụng các thẻ lồng nhau:

<Button Content=”Button1″>
        <Button.Width>100</Button.Width>
</Button>

Cú pháp trên chỉ thường được dùng cho những property có kiểu dữ liệu phức tạp, ví dụ với property Grid.RowDefinitions:

 

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
...
</Grid>

 

Trong Code-Behind:

Bởi vì các thành phần WPF đã tạo sẵn các wrapper (get/set), ta sử dụng như các CLR property thông thường:

double width = button1.Width;
button1.Width = 100;

Bạn cũng có thể sử dụng hai phương thức GetValue(DependencyProperty) và SetValue(DependencyProperty, value), tuy nhiên nên sử dụng cách trên:

double width = (double)button1.GetValue(Button.WidthProperty);
button1.SetValue(Button.WidthProperty,100d);

Tạo Dependency Property

Để tạo một dependency property, class của bạn phải kế thừa từ DependencyObject. Sau đó bạn tạo một static field kiểu DependencyProperty và khởi tạo nó bằng cách gọi phương thức DependencyProperty.Register().

Phương thức static dùng để đăng kí một property vào dictionary, gồm 3 overload và có kiểu trả về là DependencyProperty. Overload đầy đủ nhất có dạng (C#):

public static DependencyProperty Register(
         string name,
         Type propertyType,
         Type ownerType,
         PropertyMetadata typeMetadata,
         ValidateValueCallback validateValueCallback
)

Trong đó:

-          name: tên của dependency property sẽ đăng kí, theo tiêu chuẩn đặt tên của .NET thì bạn nên thêm hậu tố là Property (ví dụ WidthProperty).

-          propertyType: kiểu dữ liệu của property.

-          ownerType: kiểu dữ liệu chứa property (đăng kí property)

-          typeMetadata: giá trị của property (Xem: System.Windows.PropertyMetadata)

-          validateValueCallback: delegate của phương thức dùng để kiểm tra tính hợp lệ của dữ liệu mỗi khi được gán cho property. Delegate này có dạng:

public delegate bool ValidateValueCallback(
     Object value
)

Xem: System.Windows.ValidateValueCallback

Như vậy ta có thể tạo class Student gồm một dependency property Age cơ bản như sau, với giá trị ban đầu của Age là 6:

 

public class Student: DependencyObject
{
    public static readonly DependencyProperty AgeProperty =
        DependencyProperty.Register("Age", typeof(int),
                                    typeof(Student),
                                    new PropertyMetadata(6)
                                   );

    // CLR Property Wrapper
    public int Age
    {
        get { return (int)GetValue(AgeProperty); }
        set { SetValue(AgeProperty, value); }
    }

}

 

Kiểm tra hợp lệ cho Property (Property Validation)

Value Changed Callback và Coerce Value Callback

Contructor của PropertyMetadata bao gồm overload cho phép truyền vào các delegate callback dùng để kích hoạt các phương thức quản lý dữ liệu được gán cho property. Hai loại callback này gồm:

-          Value Changed Callback: kích hoạt khi giá trị của property bị thay đổi.

-          Coerce Value Callback: kích hoạt khi phương thức DependencyObject.CoerceValue() được gọi (tự động) để “ép” giá trị của property về giá trị hợp lệ nếu nó nằm ngoài vùng dữ liệu cho phép.

Như vậy ta có thể sửa lại ví dụ trên như sau:

 

public static readonly DependencyProperty AgeProperty =
    DependencyProperty.Register("Age", typeof(int),
                                typeof(Student),
                                new PropertyMetadata(6,AgeChangedCallback, AgeCoerceCallback)
                               );

private static void AgeChangedCallback(
    DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // do something
}

private static object AgeCoerceCallback(DependencyObject d, object baseValue)
{
    int age = (int)baseValue;

    if (age < 6)
        age = 6;
    else if(age>50)
        age = 50;

    return age;
}

 

Validate Value Callback

Đây là loại callback được dùng để kiểm tra tính hợp lệ của dữ liệu gán cho property. Phương thức callback này sẽ kiểm tra trước khi Coerce Value Callback được gọi. Giá trị trả về của Validation callback là kiểu boolean với giá trị true tương ứng với dữ liệu hợp lệ. Khi dữ liệu được kiểm tra là không hợp lệ, callback này sẽ ném ra một ngoại lệ ArgumentException.

 

private static bool AgeValidateCallback(object value)
{
    if(value is int)
    {
        int age = (int)value;
        return age >= 0;
    }
    return false;
}

 

Mã nguồn hoàn chỉnh của lớp Student

Tạo một project WPF và thêm vào lớp Studen.cs.

Student.cs:

 

public class Student: DependencyObject
{
    public static readonly DependencyProperty AgeProperty =
        DependencyProperty.Register("Age", typeof(int),
                                    typeof(Student),
                                    new PropertyMetadata(6,AgeChangedCallback, AgeCoerceCallback),
                                    AgeValidateCallback
                                   );

    // CLR Property Wrapper
    public int Age
    {
        get { return (int)GetValue(AgeProperty); }
        set { SetValue(AgeProperty, value); }
    }

    private static void AgeChangedCallback(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // do something
    }

    private static object AgeCoerceCallback(DependencyObject d, object baseValue)
    {
        int age = (int)baseValue;

        if (age < 6)
            age = 6;
        else if(age>50)
            age = 50;

        return age;
    }
    private static bool AgeValidateCallback(object value)
    {
        if(value is int)
        {
            int age = (int)value;
            return age >= 0;
        }
        return false;
    }
}

 

Trong tập tin Window1.xaml.cs, bạn sửa lại lớp Window1 như sau:

 

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        Student st=new Student();
        try
        {
            st.Age=4;
            MessageBox.Show(st.Age.ToString());     // Output: 6 (Coerce Value Callback)

            st.Age=-1; // ArgumentException (Validate Value Callback)
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

}

 

http://yinyangit.wordpress.com

 Chia sẻ qua: 
Hot!
Ý kiến bạn đọc

These items will be permanently deleted and cannot be recovered. Are you sure?

Gallery

image

Maecenas viverra rutrum pulvinar

Maecenas viverra rutrum pulvinar! Aenean vehicula nulla sit amet metus aliquam et malesuada risus aliquet. Vestibulum rhoncus, dolor sit amet venenatis porta, metus purus sagittis nisl, sodales volutpat elit lorem…

Read more

Text Links

Thiết kế logo chuyên nghiệp Insky
DAFABET
W88 w88b.com/dang-ky-tai-khoan-w88
W88
Copyright © 2011 - 2012 vietshare.vn by phamkhuong102@gmail.com doanhkisi2315@gmail.com. All rights reserved.