۱۳۸۸/۱۲/۱۴

خلاصه‌اي كاربردي در مورد Observable collection


Observable collection در WPF را مي‌توان نوعي ليست جنريك ويژه تعريف كرد كه زمانيكه به كنترلي بايند شد، كنترل را از تغييرات خودش آگاه مي‌كند. براي مثال اگر آيتمي به اين ليست اضافه شد بلافاصله آن آيتم را در كنترل مقيد به آن نيز خواهيد ديد، به همين ترتيب در مورد ويرايش و يا حذف يك آيتم، بدون نياز به كوچكترين تماسي با كنترل مورد نظر. براي مثال اگر مقدار يك خاصيت را تغيير داديد، بلافاصله بدون اينكه به كنترل مقيد به آن اعلام كنيم كه لطفا اين مورد ويژه را براي من تغيير بده، شاهد نتيجه‌ي نهايي خواهيم بود.



اما استفاده‌ي پيشرفته از اين ليست جنريك ويژه به همينجا ختم نشده و حين اضافه كردن كمي پيچيدگي به برنامه مشكلات عديده‌اي بروز مي‌كنند كه آن‌ها را جهت دسترسي ساده‌ي بعدي در زير ليست مي‌كنم:

الف) اصلا Observable collection چيست؟ چكار مي‌كند؟
List vs ObservableCollection vs INotifyPropertyChanged in Silverlight

ب) نمي‌توانم از اين مجموعه‌ي اشياي خودآگاه سازنده در يك ترد استفاده كنم. مشكل كجاست؟
اين روزها نمي‌توان يك برنامه‌ي دسكتاپ خوب را بدون استفاده از تردها متصور شد. اما به محض سعي در به روز رساني اين ليست جنريك در يك ترد ديگر (ترد ديگر منظور هر تردي بجز ترد اصلي برنامه است كه كار مديريت رابط كاربر را به عهده دارد) خطاي زير ظاهر مي‌شود:
This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread

راه حل:
Adding to an ObservableCollection from a background thread

ج) يكي از خاصيت‌هاي يك شيء اين ليست جنريك ويژه را تغيير داده‌ام. اما هيچ تغييري در كنترل بايند شده به آن مشاهده نمي‌كنم. مشكل در كجاست؟
راه حل: پياده سازي اينترفيس INotifyPropertyChanged را فراموش كرده‌ايد:
Data Binding in WPF with the Monostate Pattern

د) خوب، اين كه خيلي دردسر دارد! راه ساده‌تري براي تعريف اين موارد نيست؟!
هوشمندانه‌ترين روشي كه براي حل اين مساله تابحال ديده‌ام:
An easier way to manage INotifyPropertyChanged

ه) زمانيكه اين يك ليست جنريك خودآگاه سازنده را به يك مثلا listview بايند مي‌كنم، ديگر نمي‌توانم با استفاده از متد clear items آن كنترل، نسبت به خالي كردن نماي ظاهري آن اقدام كنم. چكار بايد كرد؟
خطاي مشاهده شده:
Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead

راه حل:
همان Observable collection اصلي را تخليه كنيد، UI به صورت خودكار به روز خواهد شد.

و) اضافه كردن رنجي از اطلاعات به آن به صورتي يكباره ممكن است كند باشد. چه بايد كرد؟
راه حل:
AddRange for ObservableCollection in Silverlight 3