مرتضي درزي
مرتضي درزي
خواندن ۹ دقیقه·۵ سال پیش

پياده سازي درست Binding در Wpf DataGrid

تو نرم افزار هاي ويندوزي از DataGrid براي نمايش اطلاعات بصورت جدول استفاده ميشه و wpf هم با قدرت فوق العاده اش در binding به طراحي جدول هايي بسيار عالي كمك زيادي كرده ، اما اين وسط بسته به نوع طراحي بايد چند چيز رو رعايت كنيم كه سعي ميكنم در اين نوشتار به اونا بپردازم . قبل از هر چيز بزاريد ميز كارمون رو بچينيم .

فرض كنيد يه نرم افزار داريم كه ليستي از اطلاعات اشخاص ( PersonList ) رو بصورت DataGrid جدول بهمون نشون ميده و ما هم ميتونيم به اين اطلاعات اضافه كنيم يا از روش كم كنيم يا حتي اطلاعات رو تغيير بديم.خوب براي اينكار بصورت ابتدايي يه صفحه به شكل زير طراحي ميكنيم

همانطور كه ميبينيد يه DataGrid داريم و چند تا Button كه قراره كارهايي رو روي اطلاعات جدول انجام بدن . مثلا دكمه Add يه "شخص جديد" جديد به جدول اضافه ميكنه و Remove هم اولين رديف رو حذف ميكنه و Edit نام اولين شخص رو به "يه اسم ديگه" تغيير ميده ( جهت سهولت كار خيلي ابتدايي فرض شده )

براي پياده سازي منطق برنامه هم از MVVM و ViewModel استفاده شده كه به سادگي هر چه تمام تر View به ViewModel بايند شده ( از GalaSoft.MvvmLight هم استفاده كردم ) ( ويرگول چرا با gist مشكل داري ؟ مجبور شدم كد رو مستقيم اينجا بزارم )

<StackPanel Grid.Row=&quot0&quot Margin=&quot10&quot Orientation=&quotHorizontal&quot> <Button Width=&quot75&quot HorizontalAlignment=&quotLeft&quot VerticalAlignment=&quotTop&quot Command=&quot{Binding Delete}&quot Content=&quotDelete&quot /> <Button Width=&quot75&quot HorizontalAlignment=&quotLeft&quot VerticalAlignment=&quotTop&quot Command=&quot{Binding Edit}&quot Content=&quotEdit&quot /> <Button Width=&quot75&quot HorizontalAlignment=&quotLeft&quot VerticalAlignment=&quotTop&quot Command=&quot{Binding Add}&quot Content=&quotAdd&quot /> </StackPanel> <DataGrid Grid.Row=&quot1&quot AutoGenerateColumns=&quotTrue&quot ItemsSource=&quot{Binding PersonList}&quot /> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.DataContext = new SimpleViewModel(); } } public class SimpleViewModel : ViewModelBase { public SimpleViewModel() { PersonList = new List<Person>(){ new Person(){Name =&quotعلي&quot}, new Person(){Name =&quotمحمود&quot}, new Person(){Name =&quotمرتضي&quot}, new Person(){Name =&quotحامد&quot}, }; } public List<Person> PersonList { get; set; } private RelayCommand _Delete; public RelayCommand Delete { get { return _Delete ?? (_Delete = new RelayCommand( () => { PersonList.Remove(PersonList.First()); })); } } private RelayCommand _Add; public RelayCommand Add { get { return _Add ?? (_Add = new RelayCommand( () => { PersonList.Add(new Person() { Name = &quotشخص جديد&quot }); })); } } private RelayCommand _Edit; public RelayCommand Edit { get { return _Edit ?? (_Edit = new RelayCommand( () => { PersonList.First().Name = &quotيه اسم ديگه&quot })); } } }

اجراي اوليه با List :

با استفاده از يه List و bind كردن اون به DataGrid خيلي راحت ميتونيم اطلاعات رو در جدول به نمايش بگذاريم و همونطور كه ميبينيد نمايش اوليه اطلاعات مشكلي نداره و همه چيز عاليه .

اما ميريم سراغ دكمه ها . هر كدوم يك از دكمه ها رو كه بزنيد اطلاعات در ViewModel تغيير ميكنه ( ميتونيد با BraekPoint چكش كنيم ) ولي در جدول هيچ اتفاقي نمي افته ! چي شده ؟ ما كه binding رو درست اجرا كرديم و اطلاعات هم به ليست اضافه شده چرا تو جدول هيچ تغييري نمي بينيم ؟

مشكل اينجاست كه كسي نرفته به DataGrid بگه كه اطلاعات تغيير كرده شما خودتو به روز كن ! خوب اينو كي بايد بگه و كجا ؟

اجراي دوم با ObservableCollection :

بجاي استفاده از List از ObservableCollection استفاده ميكنيم

public ObservableCollection<Person> PersonList { get; set; }

خوب ObservableCollection چيه ؟ همون List ولي اينترفيس هايي به نام INotifyCollectid INotifyPropertyChanged رو هم پياده سازي كرده . اين يعني اينكه وقتي اطلاعات ObservableCollection رو " اضافه - كم - جابجا كنيد " خودش ميره به binding ميگه من تغيير كردم و اونم ميره به DataGrid ميگه آقا خودتو بروز كن

خوب حالا كه ليست اشخاص رو تبديل كرديم به ObservableCollection ميريم برنامه رو اجرا كنيم و دكمه ها رو امتحان ميكنيم . Add , Remove كار ميكنه . يعني به محض اضافه شدن يا كم شدن از ليست PersonList ، جدول هم تغيير ميكنه

اما دكمه Edit كار نميكنه يا حداقل جدول به روز نميشه . اگر باز هم از BreakPoint استفاده كنيد مبينيد اطلاعات در PersonList تغيير كرده ولي جدول خبر نداره !! البته ممكنه تا همينجا مشكل شما حل شده باشه و نيازي به دكمه Edit نداشته باشيد ( بسته به نوع طراحي ) ولي اگه اونو هم ميخواهيد بريم يه مرحله ديگه

اجراي سوم با INotifyPropertyChanged :

دليل مشكل بالا اين بود كه اطلاعات در داخل يك آيتم Person تغيير كرده و همانطور كه گفتيم ObservableCollection فقط اضافه و كم و جابجا شدن هر آيتمش رو خبر ميده ولي ما ميخوايم تغيير اطلاعات داخل يه آيتم رو هم بهمون خبر بده تا به DataGrid بگيم خودشو به روز كنه

اينكار با پياده سازي Person از INotifyPropertyChanged قابل انجامه . يه سري كد هم به آخر اين كلاس اضافه ميشه يه قطعه كد هم به Name و تمام

public class Person : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set {
name = value;
NotifyPropertyChanged(&quotName&quot);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}

حالا ميريم اين اجرا رو داشته باشيم . همه دكمه ها خوب كار ميكنن و ميتونيم با دكمه Edit اطلاعات يك شخص رو تغيير بديم و در جدول هم همزمان نتيجه رو ببينيم .

اميدوارم مفيد بوده باشه ...



برنامه نويسيwpfbindingDataGridنرم افزار
برنامه نویس فرانت ( ریکت )
شاید از این پست‌ها خوشتان بیاید