تعریف یک ویژگیوابسته(DependencyProperty) در WPF
پیش از شروع لازم است تعریفی از ویژگی داشتهباشیم، یک ویژگی، خاصیت و یا پراپرتی(Property) {در تمامی این مقاله ویژگی به معنی پراپرتی میباشد} یک مکانیزم انعطافپذیر برای خواندن، نوشتن و یا محاسبه یک فیلد یا متغیر میباشد. ویژگی را بهگونهای میتوان استفاده کرد که گویی یک متغیر عمومی است، یعنی مانند تعریف یک متغیرعمومی(Public) در یک کلاس عملمیکند. اما در متغیرعمومی امکان کنترل داده ورودی وجود ندارد، برای نمونه فرض کنید در کلاس شخص(Person) یک متغیرعمومی از نوع اعداد صحیح برای ورود اطلاعات قد افراد تعریف شده باشد، اما میدانیم قد افراد نمیتواند بیش از 250سانتیمتر باشد، ولی بدلیل تعریف عمومی آن، امکان کنترل قد برای جلوگیری از ورود اطلاعات نادرست نیست. اما اگر همین متغیر را بهصورت یک ویژگی تعریفکنیم، امکان اعتبارسنجی(Validate) برای آن وجود دارد. در برنامهنویسی استاندارد(شاید استاندارد واژه مناسبی برای آن نباشد) وقتی میخواهید یک ویژگی تعریفکنید نخست یک متغیر خصوصی(Private variable) تعریفمیکنید و با دستورهای Get و Set مقادیر ویژگی را تنظیم(Set) کرده و یا(Get) برمیگردانید(به این ویژگیها CLR Property که مخفف Common Language Runtime Property است گفتهمیشود).
سخن فوق را با مثال نشان میدهیم. در زیر نمونه ساده از آن قراردارد:
public class Person
{
public int Height=0;
private string _name="";
public string Name
{
get {return _name;}
set {_name = value;}
}
}به کلاس Person تعریف شده توجهکنید، متغیرعمومی Height و ویژگی Name هر دو از دید یک کلاس خارج از کلاس Person یک کارکرد را دارند، اما برای ویژگی Name این امکان که بتوان داده ورودی را پیش از ثبت کنترل کرد وجود دارد.
اما در WPF تعریف یک ویژگی با تعریف استاندارد آن تفاوتهایی دارد که در زیر به آنها اشاره میگردد. در WPF ویژگیوابسته تعریفمیگردد(چراکه میخواهیم در تمپلیت، استایل، ریسورس، دیتابایندینگ و ... استفادهکنیم.). در زیر یک ویژگیوابسته تعریف شده است.
class Person:DependencyObject
{
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register(
"Name",
typeof(string),
typeof(Person),
new FrameworkPropertyMetadata(""));
public string Name
{
get {return (string)GetValue(NameProperty);}
set { SetValue(NameProperty, value); }
}
}توجه کنید برای تعریف متغیروابسته لازم است که کلاس ما از یک کلاس به نام DependencyObject ارثبری داشتهباشد(و یا هر کلاس دیگری که از DependencyObject ارث بردهباشد).
از خط 3 تا 8 مشابه همان تعریف متغیرخصوصی در بالا میباشد با این تفاوت که میتوان برای اعتبارسنجی نیز تابعی تعریف کرد، برای تعریف یک ویژگیوابسته لازم است نام ویژگی(در اینجا Name) به همراه کلمه Property نوشتهشود، دراینجا NameProperty. سپس اقدام به رجیسترکردن آن میکنیم، پارامتر نخست نام ویژگی است که بهصورت یک رشته(string) میباشد(در اینجا "Name"), سپس نوع ویژگی(اینجا نام از جنس رشته است) تعریف میگردد و سپس کلاسی که قراراست این ویژگی وابسته به آن باشد تعریف میشود(توجه کنید در اینجا کلاسمان همان Person است اما ممکن است بنابرنیاز شما نام کلاس دیگری را قراردهید). و درآخر یک PropertyMetadata و یا FrameworkPropertyMetadata تعریفمیکنید که مقادیر اولیه و تابع اعتبارسنجی و... درون آن تعریف میشود.
خطهای 11و12 دقیقا معادل دستورات Get و Set در تعریف استاندارد است.
خوب همه این تعاریف بجای خود، اما اینهمه پیچیدگی برای چیست؟
- ویژگیوابسته حتی پس از ایجاد کلاس تا زمانی که مقداری برای آن تنظیم نشود حافظه اشغال نمیکند.
- ویژگیوابسته درون یک Dictionary قراردارد(یعنی یک key و یک value) که این دیکشنری توسط DependencyObject تهیهمیگردد(درست است که ویژگی درون کلاس تعریف میشود اما در واقع درون یک دیکشنری که توسط DependencyObject ایجاد میگردد قرارمیگیرد و نه درون کلاس، فقط تعریف آن درون کلاس است).
- از ویژگیوابسته در زمل(XAML) استفاده میگردد. به زبانی ساده ویژگیوابسته مربوط و وابسته به زمل است(نه کلاسمان) و باعث میگردد تا میان زمل و کلاسی که تعریفکردهایم ارتباط برقرارگردد.
در زیر یک نمونه دیگر تعریف شده:
class Person:DependencyObject
{
private List<string> _listofFamily = new List<string>();
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register(
"Name",
typeof(string),
typeof(Person),
new PropertyMetadata(""));
public string Name
{
get {return (string)GetValue(NameProperty);}
set { SetValue(NameProperty, value); }
}
public static readonly DependencyProperty FamilyProperty =
DependencyProperty.Register("Family", typeof(string), typeof(Person), new
PropertyMetadata("", new PropertyChangedCallback(OnFamilyChanged)));
public string Family
{
get { return (string)GetValue(FamilyProperty); }
set { SetValue(FamilyProperty, value); }
}
private static void OnFamilyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
Person _person = d as Person;
_person.OnFamilyChanged(e);
}
private void OnFamilyChanged(DependencyPropertyChangedEventArgs e)
{
_listofFamily.Add((string)e.NewValue);
}
}برای اطلاعات بیشتر به اینجا و اینجا مراجعه شود و یا میتوان در اینترنت جستجوکرد.

