در مورد بررسی ارتباط با دادهها در WPF باید سه مورد را بشناسیم:
- DataContext: این شیء اتصالش را به منبع دادهها برقرار کرده و هر موقع دادهای را نیاز داریم، از طریق این شیء تامین میشود.
- DataBinding: یک واسطه بین DataContext و هر آن چیزی است که قرار است از دادهها تغذیه کند. در تعریفی رسمیتر میگوییم: روشی ساده و قدرتمند بوده و واسطی است بین مدل تجاری و رابط کاربری. هر زمانی که دادهای تغییر کند، ما را آگاه میسازد که میتواند یک ارتباط یک طرفه یا دو طرفه باشد.
- DataTemplate: نحوهی فرمت بندی و نمایش دادهها را تعیین میکند.
ابتدا قبل از هر چیزی کلاس فرم قبلی را پیاده سازی میکنیم. در این پیاده سازی از یک enum برای انتخاب زمینههای کاری هم کمک گرفته ایم و هچنین با یک متد ایستا، منبع دادهی تک رکوردی را جهت تست برنامه آماده کردهایم:
public enum FieldOfWork { Actor=0, Director=1, Producer=2 } public class Person { public string Name { get; set; } public bool Gender { get; set; } public string ImageName { get; set; } public string Country { get; set; } public DateTime Date { get; set; } public IList<FieldOfWork> FieldOfWork { get; set; } public static Person GetPerson() { return new Person() { Name = "Leo", Gender = true, ImageName ="man.jpg", Country = "Italy", Date = DateTime.Now }; } }
حالا لازم است که این منبع داده را در اختیار DataContext بگذاریم. وارد بخش کد نویسی شده و در سازندهی پنجره کد زیر را مینویسیم:
DataContext = Person.GetPerson();
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = Person.GetPerson(); } }
همانطور که میدانید متن کنترل TextBox توسط خصوصیت Text پر میشود و برای همین در این خصوصیت مینویسیم:
Text="{Binding Name}"
Source="{Binding ImageName}"
اطلاع از به روزرسانی در منبع دادهها:
حال این نکته پیش میآید که اگر همین اطلاعات دریافت شده در مدل منبع داده تغییر کند، چگونه میتوانیم از این موضوع مطلع شده و همین اطلاعات به روز شده را که نمایش دادهایم، تغییر دهیم. بنابراین جهت اطلاع از این مورد، کد را به شکل زیر تغییر میدهیم.
کار را از یک کلاس آغاز میکنیم. از اینترفیس INotifyPropertyChanged ارث بری کرده و در آن یک رویداد و یک متد را تعریف میکنیم و کمی در هم در تعریف Propertyها دست میبریم. فعلا اینکار را فقط برای پراپرتی Name انجام میدهیم:
private string _name; public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } }
در بخش Setter آن خصوصیت هم باید این متد را صدا زده و نام خصوصیت را به آن پاس بدهیم تا موقعی که مدل تغییر پیدا کرد، بگوید که خصوصیت Name بوده است که تغییر کرده است.
برای اینکه بدانیم کد واقعا کار میکند و تستی بر آن زده باشیم، فعلا دکمهی Save را به Change تغییر میدهیم و کد داخل پنجره را بدین صورت تغییر میدهیم:
public partial class MainWindow : Window { private Person person; public MainWindow() { InitializeComponent(); person = Person.GetPerson(); DataContext = person; } private void Button_Click(object sender, RoutedEventArgs e) { person.Name = "Leonardo Decaperio"; } }
این کد واقعا کدی مفید جهت به روزرسانی است ولی مشکلی دارد که نام پراپرتی باید به صورت String به آن پاس شود که در یک برنامه بزرگ این مورد یک مشکل خواهد شد و اگر نام خصوصیت تغییر کند باید نام داخل آن هم تغییر کند؛ پس کد را به شکل دیگری بازنویسی میکنیم:
private string _name; public string Name { get { return _name; } set { _name = value; OnPropertyChanged(); } } private void OnPropertyChanged([CallerMemberName] string property="") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } }
OnPropertyChanged();
کد این قسمت
در قسمتهای آینده به بررسی تبدیل مقادیر و framework element و کنترلها میپردازیم.