سلامی مجدد استاد
خیلی ممنون از توضیحات پست بالاتون .
استاد ، در لینک زیر :
آها خیلی ممنون . ولی همونطور که میدونید ، از این دست اعضایی که به درد یک کلاسِ خاص نمیخوره (که جریانش را در پست قبلی توضیح دادم) و صرفا در ارتباط با View هست که معنا پیدا میکنه ، در طول پروژه ، زیادتر و زیادتر میشن . در واقع نیازهای معماری MVVM هست که این نیازِ اضافی برای این نوع اعضا را بوجود...
forum.majidonline.com
متدِ FillComboBoxByDriveInfos را به نام SetFixedDriveComboBoxItemsProperty تغییر دادم که بدنه اش را در زیر مینویسم (این متد ، در کلاس PoshtibangirToloUI هست که جزء لایه ی View محسوب میشه . وظیفه ی این متد هم پر کردنِ پروپرتی ای بنام FixedDrivesCustomItems که از نوع List<ItemsControlCustomItem> هست ، هست و این متد ، در متد سازنده ی کلاس ، فراخونی میشه . پروپرتیِ FixedDrivesCustomItems هم یکبار مقداردهی میشه و لیست درایوهای ثابت یا همون درایوهای هارد اینترنال را داره که کمبوباکس هایی که لازم هست که لیست درایوهای ثابت را داشته باشن ، به این پروپرتی ، Binding میکنن) :
C#:
private void SetFixedDriveComboBoxItemsProperty()
{
DriveInfo[] driveInfos = ExtensionMethodViewModel.GetFixedNtfsDrives();
if (driveInfos == null || driveInfos.Length < 1)
return;
this.FixedDrivesCustomItems = new List<ItemsControlCustomItem>();
foreach (DriveInfo driveInfo in driveInfos)
{
string driveInfoFormatted = this.ExtensionMethodViewModel.DriveInfoFormatted(driveInfo);
ItemsControlCustomItem comboBoxCustomItem = new ItemsControlCustomItem(driveInfoFormatted, driveInfo);
this.FixedDrivesCustomItems.Add(comboBoxCustomItem);
}
}
همونطور که قبلا در لینک بالا صحبت کردیم ، یکی از دو موضوع ام در این پست ، نقش شی کلاس DriveInfo در این متد هست (این متد بالا هم که در View هست) .
هر چند در اون پست که در بالا لینک دادم ، گفتم :
"ولی بالاخره DriveInfo که جزء لایه ی Model ام نیست ."
و DriveInfo در دات نت موجود هست ، و شاید این دلیلی باشه که بشه از شیِ DriveInfo در View هم استفاده و فراخونی کرد ، اما با این حال ، شاید بیشتر ، بشه برای شیِ DriveInfo ، نقشِ Model را متصور بود (هر چند در اعضای پروپرتی ای در View استفاده بشه) .
موافقید؟
اگه تا اینجا را درست بگم ، پس این پروپرتیِ FixedDrivesCustomItems ، بهتره که در لایه ی ViewModel مقدار دهی و پر بشه . یعنی بهتره که این متدِ SetFixedDriveComboBoxItemsProperty را به لایه ی ViewModel منتقل کنم . درست میگم؟
-------------------
حالا مشکل اینه که توی ViewModel که به پروپرتیِ FixedDrivesCustomItems (که در View هست) ، دسترسی ندارم ، چجوری از اونجا مقدار جدیدی بهش بدم (فقط نمیخوام دسترسی داشته باشم ، بلکه میخوام مقدار جدیدی به پروپرتی از ViewModel بدم) ؟
جوابش هم اینه که در ورودی این متد ، بصورت ref ، شیِ فیلدِ مربوط به این پروپرتی را بدم (چون خودِ پروپرتی که نمیشه بصورت ref پاس داد) .
مشکل دیگه اینکه اگه این پروپرتیِ FixedDrivesCustomItems ، متد RaisePropertyChanged (که با پیاده سازیِ اینترفیس IPropertyChanged انجام شد) را فراخونی کرد ، چون فیلدش را بصورت مستقیم در ViewModel مقداردهی کردیم و بنابراین قسمت set ئه پروپرتی مون با مقداردهیِ فیلدش اجرا نمیشه ، یا دسترسیِ این متدِ RaisePropertyChanged را public میگیریم و شیِ View مون را به این متد در ViewModel ارسال میکنیم و بعد از مقداردیِ فیلدش ، متدِ RaisePropertyChanged ئه PoshtibangirToloUI که جزء View محسوب میشه را فراخونی میکنیم یا حالا یه دلیگیتی پاس میدیم به همین متدِ SetFixedDriveComboBoxItemsProperty در ViewModel یا یه رویدادی یا از این قبیل کارها میکنیم برای اجرای متد RaisePropertyChanged .
درسته؟
====================================================================
یه مسئله ی دیگه و مهمتر اینکه ، من یه user control به نام DriveBackupUserControl دارم میسازم که از لحاظ ظاهری ، قراره خیلی شبیه به کنترلی که در My Computer (همون This PC) که آیکون و آیتم و نوشته ها و اطلاعات مربوط به یک درایو را نشون میده ، باشه . منتها این user control ، علاوه بر این اطلاعات ، اطلاعات بکاپ های اون درایو را نشون میده .
در واقع این user control ، اطلاعات بکاپ ها را نشون میده و همچنین بعضی از اطلاعات درایوها (که در My Computer) هست را نشون میده .
حالا من در یکی از کلاس های لایه ی Model ام ، پروپرتی ای بنام BackupStatus دارم که وضعیت بکاپ را بصورت enum ذخیره میکنه (که بکاپ در حالت عادی هست ، یا اینکه بکاپ نداره یا اینکه در شرایط هشدار دادن قرار داره) .
این پروپرتی ، برای کلاسی هست که اطلاعات کل و همه ی درایوها را ذخیره میکنه . یعنی فرضا اگه طرف 5 تا درایو داشت که وضعیت بکاپ 3 تاشون عادی بودن و یکی شون در حالت هشدار و یکی دیگه بکاپ نداشت ، این پروپرتی در این کلاس ، بدترین حالت را برمیگردونه که یکی از درایوها بکاپ نداشت (را برمیگردونه) .
اما بجز این ، مجددا همین پروپرتیِ BackupStatus در کلاسِ مجزای دیگه ای که اطلاعات بکاپِ تک تکِ درایوها را برمیگردونه ، استفاده میشه (هنوز واسه ی این کلاس ها اسم مشخص نکردم واسه ی همین اسم شون را ننوشتم) .
----------
این DriveBackupUserControl هم که کلاسی هست که مربوط به هر درایو میشه ، از پروپرتیِ BackupStatus ای که مربوط به هر درایو مجزا هستن میخواد استفاده کنه .
حالا چون این DriveBackupUserControl ، قراره که اطلاعات را توی خودش داشته باشه و کلا یه کلاس هست ، به نظرتون تکلیفش را با پروپرتیِ BackupStatus (که از نوعِ enum هست و در Model تعریف شده) ، چی کار کنم؟
این رو از این جهت میگم که قبلا چون از این پروپرتی ، برای تعیین شکل آیکون اصلی برنامه در پروپرتیِ Icon ئه TaskbarIcon میخواستم استفاده کنم ، گفتید مستقیما بیام و به پروپرتیِ BackupStatus ئه Model ام Binding کنم .
خوب اونجا که من کلاس TaskbarIcon را ایجاد نکرده بودم یا کلاسی ننوشته بودم که ازش ارث بری کنه و چندان هم نیاز نبود که در View ام ، یه پروپرتیِ BackupStatus مجددا تعریف کنم که به پروپرتیِ BackupStatus ئه Model ام Binding کنم .
----------
اما در این کلاسِ DriveBackupUserControl ، داشتنِ همچین اطلاعاتی و همچین پروپرتی هایی که شامل اطلاعات مختلفی از درایو باشه ، کاملا نیازه .
یعنی فرضا نمیتونم مثل قبل ، برای این User Control ، مستقیما Binding به Model ام انجام بدم . چون :
اولا فرضا اگه پروپرتی هایی برای این کار (پروپرتی های مربوط به اطلاعات درایو و بکاپ) را در این کلاس اش تعریف نکنم و مستقیما به پروپرتی های Model ام (که یک نمونه اش پروپرتیِ BackupStatus بود) ، Binding کنم ، فرضا اگه به پروژه ی دیگه ای بخوام این کنترل را منتقل کنم ، دردسرهای بسیار بزرگی داره و از اول باید براش به ازای هر پروژه ای که منتقل میکنم ، بجای مقداردهی پروپرتی ، از اول Binding هاش را درست کنم .
و دوما اگه پروپرتی هایی را در این کلاس اختصاص ندم و نخوام هم کنترل های مورد نظرم در این user control را توسط Binding مقداردهی کنم ، در این صورت ، هم دسترسی های اون کنترل هایی که درون user control تعریف کردم را باید public کنم که این وجهه ی خوبی نمیده و اصولی نیست و هم کد را زیاد و پیچیدگی اش را بیشتر میکنه .
=========
اگه پروپرتی هایی نظیر این پروپرتی هایی که در Model هست را در User Control تعریف کنم ، دقیقا چی کار کنم؟
چون میگید که پروپرتی هایی که از نوع Model هستن (مثل پروپرتیِ BackupStatus که از نوعِ enum ئه شخصی ای بنام BackupStatus هست که در Model تعریف کردم) را در View بخاطر نقض MVVM استفاده نکنم .
پس در این صورت فرضا به همچین enum ای اگه نیاز دارم استفاده کنم ، چی کار کنم؟
فرضا آیا پیشنهاد میدید که یه enum ئه دیگه که شامل همون اعضای enum ئه BackupStatus هستن ، اما این بار در لایه ی View تعریف کنم و بعد Binding ای بین enum ئه BackupStatus در Model با enum ئه BackupStatus در View توسط Converter انجام بدم؟
ببخشید استاد که خیلی زیاد شد .
تشکر