سئوالات و مباحث WPF

the_king

مدیرکل انجمن
سلامی مجدد استاد .
استاد ، میگم اینجا که گفتید که گفت :



اینی که در زیر میگم ، به همین معنا و مفهومی هست که اون گفته؟ :

پنجره های wpf ، فقط زمانی در مانیتورهای مختلف ، اندازه ی برابری دارند (یعنی نسبت به اینچ با هم برابرند نه در مقیاسِ پیکسل) که در هر مانیتور ، هم اینکه روی ریزولیشنِ پیش فرضِ اون مانیتور تنظیم شده باشه (یعنی اون ریزولیشن ای که مثلا در ویندوز 10 مینویسه Recomended یا در واقع ، اون مانیتور ، به همون تعداد ، پیکسل های فیزیکی داره) و هم اینکه dpi ئه هر مانیتور هم روی حالتِ پیش فرضش تنظیم شده باشه (البته نمیدونم در ویندوز 10 ، تنظیمِ بخشِ scale & layout ، همون تنظیمِ dpi ای هست ک در نسخه های قبلی ویندوز مثل xp و اینها بود یا نه . و اگه همین هه ، پس یعنی مثلا در هر مانیتور ، در بخشِ scale & layout در ویندوز 10 ، مقدارش روی 100 که Recomended هست باشه) .

در این صورت ، یعنی در صورت تنظیم ریزولیشن و dpi ده هر مانیتور به پیش فرض شون ، پنجره های wpf در اون مانیتورها ، یک اندازه نمایش داده میشن (یعنی همه شون نسبت به اینچ ، در یک اینچِ واحد و یکسانی نشون داده میشن) (یعنی دیگه نسبی نیست . یعنی درصدی نیست که در مانیتورِ 1 که 2 برابرِ مانیتورِ 2 بود (و هر دو مانیتور یک ریزولیشن را داشتن) ، پس در مانیتور مانیتور 2 که میخواد نمایش بده ، نصفِ مانیتور 1 نمایش بده که همون) .

این درکی که از مطلب بالا دارم ، درسته؟
مفهومش همینه؟
نمیگه فقط در این صورت exact same size میشه، میگه در این شرایط resolution independence ئه و در نتیجه حتما exact same size میشه.
هر وقت resolution independence شد ابعاد یکسان پیدا می کنه اما هر زمان ابعاد یکسان شد نمیشه نتیجه گرفت که پس بی تردید resolution independence هست. "فقط زمانی" نتیجه گیری اشتباهی ئه چون شما دارید same size رو محدود می کنید به resolution independence.
وقتی یک پنجره در دو نمایشگر در ابعاد اینچی یکسان نمایش داده بشه معنی اش این نیست که الزاما تنظیمات DPI شون پیشفرض ئه یا تفکیک پذیری نمایشگر Native ئه، اتفاقا ممکنه resolution independence نبوده و به این دلیل در ابعاد یکسان نمایش داده شده که تنظیمات DPI یا Resolution با دقت مشخص شده.
توجه کنید که داره در مورد شرایط resolution independence بودن حرف میزنه، نه شرایط same size داشتن. ممکنه در شرایطی ابعاد یکسان شده باشه ولی مستقل از resolution نباشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نمیگه فقط در این صورت exact same size میشه، میگه در این شرایط resolution independence ئه و در نتیجه حتما exact same size میشه.
هر وقت resolution independence شد ابعاد یکسان پیدا می کنه اما هر زمان ابعاد یکسان شد نمیشه نتیجه گرفت که پس بی تردید resolution independence هست. "فقط زمانی" نتیجه گیری اشتباهی ئه چون شما دارید same size رو محدود می کنید به resolution independence.
وقتی یک پنجره در دو نمایشگر در ابعاد اینچی یکسان نمایش داده بشه معنی اش این نیست که الزاما تنظیمات DPI شون پیشفرض ئه یا تفکیک پذیری نمایشگر Native ئه، اتفاقا ممکنه resolution independence نبوده و به این دلیل در ابعاد یکسان نمایش داده شده که تنظیمات DPI یا Resolution با دقت مشخص شده.
توجه کنید که داره در مورد شرایط resolution independence بودن حرف میزنه، نه شرایط same size داشتن. ممکنه در شرایطی ابعاد یکسان شده باشه ولی مستقل از resolution نباشه.

خیلی ممنون استاد .
بله . پس اون شرایطی که گفتم (تنظیمات ریزولیشن و dpi ئه هر مانیتوری روی پیش فرض باشه) ، در این صورت در شرایط resolution independence خواهد بود و بنابراین اندازه ی پنجره های wpf در مانیتورهای مختلف (در این شرایط) یکسان خواهند بود . درسته دیگه؟

بعد اینکه تنظیمِ "scale & layout" در ویندوز 10 ، همون تنظیم dpi در ویندوزهای قبلی هست؟

--------------------------

استاد ، قضیه ی mvvm ، من چند تا مقاله را خوندم و فیلم هایی را دیدم :


و


و


و


و


چیزی که متوجه شدم را در زیر میگم ، ببینید درسته؟ :

اینکه معماری 3 لایه ، به 3 لایه ی "رابط کاربری" یا UI و "منطق تجاری" یا BL و "دسترسی داده" یا DAL تقسیم میشه .
در mvvm ، بحث لایه ی "دسترسی داده" یا DAL نیست (یعنی این لایه ، بحث اش جداست و در mvvm مطرح نیست) .
بنابراین در mvvm :
لایه ی UI ای که در معماری 3 لایه بود ، همون لایه ی view مون هست .
لایه ی BL ای که در معماری 3 لایه بود ، همون لایه ی model مون هست .
پس تا اینجا دقیق عین هم هستند .

اما در mvvm ، یک لایه ای بنام view model ، به عنوانِ لایه ی جدید (نسبت به معماری 3 لایه) وجود داره . این لایه ، این طور هست که تمام اعضایی از کلاس (های) model ای را که میخوایم در رابط کاربری مون (view مون) بایندینگ (binding) کنیم یا در view مون استفاده کنیم (و اونجا نمایش بدیم) را در کلاسی مجزا به عنوان لایه ی view model ، مقداردهی میکنیم و بجای اینکه اعضای view مون را به اعضای model مون بایندینگ کنیم (یا کارهای نمایش را انجام بدیم) ، بصورت غیر مستقیم ، اعضای view مون را به اعضای view model مون بایندینگ میکنیم (یا کارهای نمایش را انجام میدیم) .

هدف از این قضیه فکر کنم اینه که هیچ ارتباطی (حتی بایندینگ کردن) هم بین لایه ی رابط کاربری (view) و منطق تجاری نباشه تا به بهترین شیوه ، جداسازی انجام بشه و انتقال منطق تجاری به پروژه هایی که گاها از نوع دیگه مثل وب میشن و همچنین نگه داری و آپدیت کدها، به راحت ترین وجه انجام بشه . و البته کار unit testing (که نمیدونم چیه دقیقا) هم همینطور .
البته دقیق نمیدونم .

اما اگه این طور ، پس در لینک زیر :


چرا در کدهای Step 6 ، پروپرتیِ Text ئه دومین و سومین TextBox را به پروپرتیِ LastName و FullName (که در کلاس StudentModel که به عنوان کلاس Model و منطق تجاری هست) بایندینگ انجام داد؟!

اگه این طور که گفتم نیست ، پس چجوری هست؟
تشکر استاد :rose:
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
بله . پس اون شرایطی که گفتم (تنظیمات ریزولیشن و dpi ئه هر مانیتوری روی پیش فرض باشه) ، در این صورت در شرایط resolution independence خواهد بود و بنابراین اندازه ی پنجره های wpf در مانیتورهای مختلف (در این شرایط) یکسان خواهند بود . درسته دیگه؟
بله.
بعد اینکه تنظیمِ "scale & layout" در ویندوز 10 ، همون تنظیم dpi در ویندوزهای قبلی هست؟
از نظر فنی در هر ویندوزی این قابلیت ارتقاء پیدا کرده و کارکردش دقیقا مشابه ویندوز های قبلی نبوده ولی در کل بله.
استاد ، قضیه ی mvvm ، من چند تا مقاله را خوندم و فیلم هایی را دیدم :


و


و


و


و


چیزی که متوجه شدم را در زیر میگم ، ببینید درسته؟ :

اینکه معماری 3 لایه ، به 3 لایه ی "رابط کاربری" یا UI و "منطق تجاری" یا BL و "دسترسی داده" یا DAL تقسیم میشه .
در mvvm ، بحث لایه ی "دسترسی داده" یا DAL نیست (یعنی این لایه ، بحث اش جداست و در mvvm مطرح نیست) .
بنابراین در mvvm :
لایه ی UI ای که در معماری 3 لایه بود ، همون لایه ی view مون هست .
لایه ی BL ای که در معماری 3 لایه بود ، همون لایه ی model مون هست .
پس تا اینجا دقیق عین هم هستند .

اما در mvvm ، یک لایه ای بنام view model ، به عنوانِ لایه ی جدید (نسبت به معماری 3 لایه) وجود داره . این لایه ، این طور هست که تمام اعضایی از کلاس (های) model ای را که میخوایم در رابط کاربری مون (view مون) بایندینگ (binding) کنیم یا در view مون استفاده کنیم (و اونجا نمایش بدیم) را در کلاسی مجزا به عنوان لایه ی view model ، مقداردهی میکنیم و بجای اینکه اعضای view مون را به اعضای model مون بایندینگ کنیم (یا کارهای نمایش را انجام بدیم) ، بصورت غیر مستقیم ، اعضای view مون را به اعضای view model مون بایندینگ میکنیم (یا کارهای نمایش را انجام میدیم) .

هدف از این قضیه فکر کنم اینه که هیچ ارتباطی (حتی بایندینگ کردن) هم بین لایه ی رابط کاربری (view) و منطق تجاری نباشه تا به بهترین شیوه ، جداسازی انجام بشه و انتقال منطق تجاری به پروژه هایی که گاها از نوع دیگه مثل وب میشن و همچنین نگه داری و آپدیت کدها، به راحت ترین وجه انجام بشه . و البته کار unit testing (که نمیدونم چیه دقیقا) هم همینطور .
البته دقیق نمیدونم .
بله.
اما اگه این طور ، پس در لینک زیر :


چرا در کدهای Step 6 ، پروپرتیِ Text ئه دومین و سومین TextBox را به پروپرتیِ LastName و FullName (که در کلاس StudentModel که به عنوان کلاس Model و منطق تجاری هست) بایندینگ انجام داد؟!
در اون Binding ها چه چیزی می بینید که به کلاس StudentModel ربطش بده؟ شما اگر در یک کدی بنویسید Path = FirstName میره میگرده در کلاس ها ببینه یک کلاسی هست که یک FirstName داشته باشه؟ طبعا نه. بالاتر نوشته "ItemsSource = "{Binding Path = Students}، یعنی منبع داده اش Students ئه، داره با کلاس StudentViewModel ارتباط برقرار می کنه، نه StudentModel. ممکنه StudentViewModel یک منبع داده دیگری رو بکار بگیره که اونم FirstName ای داشته باشه. اون UserControl وابسته به StudentModel نیست، فقط یک منبع داده ای میخواد که FirstName ای داشته باشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله.

از نظر فنی در هر ویندوزی این قابلیت ارتقاء پیدا کرده و کارکردش دقیقا مشابه ویندوز های قبلی نبوده ولی در کل بله.

بله.

سلامی مجدد
خیلی ممنون استاد :rose:
(پیشاپیش شهادت امام علی علیه السلام را تسلیت میگم و التماس دعا در شب های قدر)


در اون Binding ها چه چیزی می بینید که به کلاس StudentModel ربطش بده؟

شما اگر در یک کدی بنویسید Path = FirstName میره میگرده در کلاس ها ببینه یک کلاسی هست که یک FirstName داشته باشه؟ طبعا نه. بالاتر نوشته "ItemsSource = "{Binding Path = Students}، یعنی منبع داده اش Students ئه، داره با کلاس StudentViewModel ارتباط برقرار می کنه، نه StudentModel. ممکنه StudentViewModel یک منبع داده دیگری رو بکار بگیره که اونم FirstName ای داشته باشه. اون UserControl وابسته به StudentModel نیست، فقط یک منبع داده ای میخواد که FirstName ای داشته باشه.

تعجب منم از همینه استاد .
الان ، در رویداد StudentViewControl_Loaded ، مقدار DataContext ئه StudentViewControl را برابر شیِ studentViewModelObject در کد سی شارپ در بخش آخر گرفت (این شی هم که از نوع StudentViewModel هست) . بنابراین مقدار Source ئه Binding در همه ی بایندینگ هایی که در شیِ فرزند (فرزند ، از لحاظ ساختار درختی . یعنی از لحاظ کدهای xaml) ئه کنترلِ StudentViewControl ، بصورت اتوماتیک ، مقدار Source ئه Binding ئه همه ی اون اشیاء ، از نوع کلاس StudentViewModel خواهد بود . یعنی Path هایی که زمان بایندینگ ، برای این کنترل یا کنترل های فرزند و نوادگانش (از لحاظ کدهای xaml) در نظر گرفته میشه ، Source ئه این Path ها ، همون کلاس StudentViewModel خواهد بود و Path هایی که بهش داده میشه را درون این کلاس (StudentViewModel) جستجو میکنه .
درست میگم؟

اگه درست میگم ، اونجایی که Path ئه بایندینگ را برای ItemsSource ئه کنترل ItemsControl ، برابر پروپرتیِ Students گرفت ، خوب چون DataContext ئه کنترلِ والدش که UserControl (که همون StudentView) هست را مقداری از نوع StudentViewModel گرفت ، پس پروپرتی ای را که به Path داده شد ، درون همون کلاس (یعنی درون StudentViewModel) جستجو میکنه . و چون پروپرتیِ Students در کلاسِ StudentViewModel وجود داره ، پس مشکلی نیست تا اینجا .

اما Path ئه بایندینگ ها برای Text ئه TextBox ها ، که برابر پروپرتی های FirstName و LastName و FullName قرار داده شدن (و بصورت صریح هم که Source ئه این بایندینگ ها مقداردهی نشدن) که این پروپرتی ها درون کلاس StudentViewModel قرار ندارن . بلکه درون کلاس Student قرار دارن .
پس چجوری اینها را پیدا میکنه؟!

البته یه سئوال دیگه هم پیش میاد که مقداردهیِ StudentViewControl.DataContext ، در رویداد StudentViewControl_Loaded انجام شد اما بایندینگ کردنِ ItemsControl و TextBox (های شامل در UserControl) ، درون کدهای xaml انجام شد . که حالا نمیدونم این تاخیر (چون کدهای رویداد Loaded ، بعد از کدهای xaml شاید اجرا بشه . درست میگم؟) باعث بشه DataContext یا همون Source شون را بشناسه یا نشناسه؟ اگه میشناسه ، چطور این اتفاق با قضیه ی این تاخیر اتفاق میافته؟

البته کدهای اون را تست نکردم که ببینم کار میکنه یا نه . چون گاها حتی در مایکروسافت هم دیدم که یه تیکه از کد را یا در صفحات دیگه مینویسن و اینها (واسه ی همین میگم شاید این هم مثل اون قضیه باشه و کدها کامل نباشن).

تشکر استاد :rose:
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد :rose:
(پیشاپیش شهادت امام علی علیه السلام را تسلیت میگم و التماس دعا در شب های قدر)






تعجب منم از همینه استاد .
الان ، در رویداد StudentViewControl_Loaded ، مقدار DataContext ئه StudentViewControl را برابر شیِ studentViewModelObject در کد سی شارپ در بخش آخر گرفت (این شی هم که از نوع StudentViewModel هست) . بنابراین مقدار Source ئه Binding در همه ی بایندینگ هایی که در شیِ فرزند (فرزند ، از لحاظ ساختار درختی . یعنی از لحاظ کدهای xaml) ئه کنترلِ StudentViewControl ، بصورت اتوماتیک ، مقدار Source ئه Binding ئه همه ی اون اشیاء ، از نوع کلاس StudentViewModel خواهد بود . یعنی Path هایی که زمان بایندینگ ، برای این کنترل یا کنترل های فرزند و نوادگانش (از لحاظ کدهای xaml) در نظر گرفته میشه ، Source ئه این Path ها ، همون کلاس StudentViewModel خواهد بود و Path هایی که بهش داده میشه را درون این کلاس (StudentViewModel) جستجو میکنه .
درست میگم؟

اگه درست میگم ، اونجایی که Path ئه بایندینگ را برای ItemsSource ئه کنترل ItemsControl ، برابر پروپرتیِ Students گرفت ، خوب چون DataContext ئه کنترلِ والدش که UserControl (که همون StudentView) هست را مقداری از نوع StudentViewModel گرفت ، پس پروپرتی ای را که به Path داده شد ، درون همون کلاس (یعنی درون StudentViewModel) جستجو میکنه . و چون پروپرتیِ Students در کلاسِ StudentViewModel وجود داره ، پس مشکلی نیست تا اینجا .

اما Path ئه بایندینگ ها برای Text ئه TextBox ها ، که برابر پروپرتی های FirstName و LastName و FullName قرار داده شدن (و بصورت صریح هم که Source ئه این بایندینگ ها مقداردهی نشدن) که این پروپرتی ها درون کلاس StudentViewModel قرار ندارن . بلکه درون کلاس Student قرار دارن .
پس چجوری اینها را پیدا میکنه؟!
به لطف مکانیسمی که برای Binding نوشته شده پیداشون میکنه. ارتباط برقرار کردن بین رشته "FirstName" و x.FirstName در NET. راحته.
منبع داده Students ئه که اسمش هم صریحا در "ItemsSource = "{Binding Path = Students} اومده.
این Students یک مجموعه است که اعضاء اش از نوع Student ئه، پس نوع داده اعضاء هم برای هر روالی که بخواد اعضاء رو پیمایش کنه مشخص ئه. پیدا کردن مشخصه ای با نام رشته ای "FirstName" در نوع داده Student یا هر نوع داده دیگری هم که کار پیچیده ای نیست. خود شما هم می توانید با Type.GetProperty در نوع داده فلان مشخصه ای با نام "FirstName" رو پیدا کنید و مقدارش رو در شیء فلان بخونید یا تغییر بدهید، بدون اینکه از قبل بدونید که اون نوع داده که الان یک object ئه قراره چی باشه.

مثل هر مکانیسم هوشمند دیگه ای که در NET. وجود داره، یک کدی هست که میاد مشخصه های داخل کلاس نوع x که از قبل اطلاعاتی در مورد x نداره رو بررسی می کنه. میدونید که System.Reflection میتونه اطلاعات ساختار هر نوع داده ای بررسی کنه، پس پیدا کردن مشخصه FirstName در اعضاء مجموعه Students و خوندن مقدارشون کار عجیبی نیست. کافیه یک کدی در روال باشه که در شیء اطلاعات مشخصه ای با نام فلان رو بخونه.
همانطور که شما با XmlSerializer خیلی ساده اطلاعات داخل یک شیء از کلاس x رو به متن xml تبدیل می کنید یا از xml به شیء برمیگردونید. اون XmlSerializer که همه کلاس های نانوشته رو از قبل نمیشناسه، درست اون زمانی که نوع شیء رو مشخص کردید باید بررسی اش کنه. به کمک System.Reflection ساختار ناشناخته x رو پیمایش می کنه و بر اساسش فایل xml تولید می کنه.

البته یه سئوال دیگه هم پیش میاد که مقداردهیِ StudentViewControl.DataContext ، در رویداد StudentViewControl_Loaded انجام شد اما بایندینگ کردنِ ItemsControl و TextBox (های شامل در UserControl) ، درون کدهای xaml انجام شد . که حالا نمیدونم این تاخیر (چون کدهای رویداد Loaded ، بعد از کدهای xaml شاید اجرا بشه . درست میگم؟) باعث بشه DataContext یا همون Source شون را بشناسه یا نشناسه؟ اگه میشناسه ، چطور این اتفاق با قضیه ی این تاخیر اتفاق میافته؟
تاخیر مادامی که نیاز به داده قبل از برقراری ارتباط رخ نده مشکلی ایجاد نمی کنه. BindingPath یک PropertyPath ئه که Path اش یک string ئه. این string بودن یعنی اسم مشخصه رو بصورت رشته بخاطر میسپاره. میتونه هر زمانی که لازم شد دنبال مشخصه ای با اون نام بگرده، لازم نیست همون لحظه که مقدار Path رو گرفت ارتباط برقرار کنه، میتونه بعدا اینکار رو بکنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد
خیلی ممنون استاد .
استاد در لینک زیر درباره ی mvvm :


شکلی بصورت زیر رسم کرده :


mvvm.png



ببینید اینهایی که میگم ، درستن؟ :

خوب میدونیم که view (اغلب) توسط DataBinding با پروپرتی و کلا اعضای ViewModel ارتباط برقرار میکنه .

حالا تغییرِ مقادیرِ (معمولا پروپرتی هایی) که در ViewModel هستند ، لایه ی Model ، این تغییرِ مقادیر را با استفاده از Notification ها (مثلا با پیاده سازی اینترفیسِ INotifyPropertyChanged که درون لایه ی Model پیاده سازی میشه) به پروپرتی های لایه ی ViewModel اطلاع رسانی میشه .

این کار توسط Notification ها انجام میشه اما توسط binding کردنِ پروپرتی های ViewModel با پروپرتی های (نظیرشون در) Model انجام نمیشه چون اگه binding ای انجام بگیره ، باز همون ارتباطی که دو پروپرتی را به هم وابسته میکنه ، وجود داره اما mvvm اومد که این وابستگی را بین این لایه ها از بین ببره . اما ارتباط از طریقِ Notification ها ، ارتباطِ وابسته به هم نیست . صرفا اطلاع رسانی از تغییرِ مقدار پروپرتی هاست .

اما سئوال من اینهان :
1) حالا اگه بخوایم تغییر پروپرتیِ لایه ی ViewModel را به پروپرتیِ های لایه ی Model مخابره کنیم (تا مقادیرِ پروپرتی های لایه ی Model ، همون مقدارِ پروپرتیِ لایه ی ViewModel بشن) ، آیا باز توسط Notification ها باید این کار را کنیم؟
یعنی باید INotifyPropertyChanged را در لایه ی ViewModel هم پیاده سازی کنیم تا به لایه ی Model ، تغییر پروپرتی را مخابره کنه؟ (علاوه بر اینکه این اینترفیس را در لایه Model برای خبر دادن به لایه ی ViewModel پیاده سازی کرده بودیم) .

اگه این طوره ، پس چرا Notification برای مخابره از لایه ی ViewModel به لایه ی Model در عکس بالا نیامد؟
و اگه این طور نیست ، پس این مخابره ی تغییرات ، چجوری باید انجام بشه؟


2) منظور از "ViewModel Update the Model" که در عکس بالا برای ارتباط برقرار کردنِ لایه ی ViewModel با لایه ی Model هست ، چیه و با چه الگویی این کار انجام میشه؟
آیا همین پیاده سازیِ INotifyPropertyChanged در لایه ی ViewModel منظورشونه؟


3) خوب ، برای ارتباط برقرار کردن بین لایه ی View با ViewModel ، از binding (حالا یک طرفه یا دو طرفه) استفاده میشه دیگه . درسته؟

پس نیازی به Notification دادن از سمت لایه ی ViewModel به سمت لایه ی View نیازی نیست دیگه ؟
پس چرا در عکس بالا ، برای ارتباط برقرار کردنِ ViewModel با View ، از Notification استفاده شده (که لایه ی ViewModel به لایه ی View ، برای ارتباط برقرار کردن ، Notification میفرسته) ؟
وقتی binding انجام میشه ، دیگه چه نیازی به Notification هست؟

همچنین اگه اشتباه نکنم ، در متن زیر :

In order for the view model to participate in two-way data binding with the view, its properties must raise the PropertyChanged event. View models satisfy this requirement by implementing the INotifyPropertyChanged interface, and raising the PropertyChanged event when a property is changed.

میگه که اگه میخوایم ViewModel با View ، بایندینگِ دو طرفه انجام بده ، لایه ی ViewModel باید اینترفیسِ INotifyPropertyChanged را پیاده سازی کنه .
خوب چرا و چه نیازی هست وقتی که binding انجام میشه؟ یا باید بایندینگ انجام بشه یا باید Notify بدیم دیگه . معنای خاصی نداره هم بایندینگ کنیم و هم Notify بدیم .
من یه کم گیج شدم .

تشکر استاد :rose:
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد .
استاد در لینک زیر درباره ی mvvm :


شکلی بصورت زیر رسم کرده :


mvvm.png



ببینید اینهایی که میگم ، درستن؟ :

خوب میدونیم که view (اغلب) توسط DataBinding با پروپرتی و کلا اعضای ViewModel ارتباط برقرار میکنه .

حالا تغییرِ مقادیرِ (معمولا پروپرتی هایی) که در ViewModel هستند ، لایه ی Model ، این تغییرِ مقادیر را با استفاده از Notification ها (مثلا با پیاده سازی اینترفیسِ INotifyPropertyChanged که درون لایه ی Model پیاده سازی میشه) به پروپرتی های لایه ی ViewModel اطلاع رسانی میشه .
بله.
این کار توسط Notification ها انجام میشه اما توسط binding کردنِ پروپرتی های ViewModel با پروپرتی های (نظیرشون در) Model انجام نمیشه چون اگه binding ای انجام بگیره ، باز همون ارتباطی که دو پروپرتی را به هم وابسته میکنه ، وجود داره اما mvvm اومد که این وابستگی را بین این لایه ها از بین ببره . اما ارتباط از طریقِ Notification ها ، ارتباطِ وابسته به هم نیست . صرفا اطلاع رسانی از تغییرِ مقدار پروپرتی هاست .
Notification ارتباط برقرار نمی کنه، همانطور که خودتون گفتید صرفا اطلاع رسانی است. برای همین هیچ وابستگی ای از هیچ سمتی بوجود نمیاره. شیء Model صرفا به هر موجودیتی که به رخداد PropertyChanged اش متدی متصل کرده اطلاع میده که مقدار مشخصه فلان من در این لحظه تغییر کرد. رخ دادن این رخداد وابستگی نیست.
اما سئوال من اینهان :
1) حالا اگه بخوایم تغییر پروپرتیِ لایه ی ViewModel را به پروپرتیِ های لایه ی Model مخابره کنیم (تا مقادیرِ پروپرتی های لایه ی Model ، همون مقدارِ پروپرتیِ لایه ی ViewModel بشن) ، آیا باز توسط Notification ها باید این کار را کنیم؟
چنین چیزی نداریم. ViewModel فقط رابط ئه، خودش چیزی نداره که بخواد در Model منعکس بشه. کدوم پروپرتی ها اش؟
فرضا Student یک مشخصه به نام FirstName داره، مرجع FirstName در کل برنامه همین Student ئه، داده ها از اشیاء Student میان.
مقدار FirstName از مشخصه Student خونده و نوشته میشه. اگر FirstName تغییر کنه در خود Student اتفاق افتاده، خودش انجام دهنده تغییر ئه، برای همین Student ئه که به بقیه اطلاع میده که این مقدار تغییر کرد. سایر اشیاء بیان بهش بگن مقدار مشخصه ات تغییر کرده و خبر نداری؟ همچین وضعیتی نداریم. میشه FirstName تغییر کنه و Student بی خبر باشه؟
2) منظور از "ViewModel Update the Model" که در عکس بالا برای ارتباط برقرار کردنِ لایه ی ViewModel با لایه ی Model هست ، چیه و با چه الگویی این کار انجام میشه؟
منظور اینه که تغییراتی که در سمت View بوجود اومده و بخاطرش داده ای باید تغییر کنه توسط ViewModel به Model منتقل میشه تا Model داده رو در منبعی که باهاش در ارتباط ئه ثبت کنه و به روز بشه. ما نمیدونیم منبع داده اون Model چیه، ممکنه یک بانک اطلاعاتی در سروری اون سر دنیا باشه یا نتیجه یک پردازش محاسباتی.
فرضا در TextBox ای مقداری تغییر می کنه که با Binding به FirstName متصل ئه. اون ViewModel رابطی بین FirstName در Student و اون TextBox ئه. پس باید به Student مقدار جدید TextBox رو برسونه تا مقدار مشخصه FirstName عوض بشه.
آیا همین پیاده سازیِ INotifyPropertyChanged در لایه ی ViewModel منظورشونه؟
نه.
3) خوب ، برای ارتباط برقرار کردن بین لایه ی View با ViewModel ، از binding (حالا یک طرفه یا دو طرفه) استفاده میشه دیگه . درسته؟
بله.
پس نیازی به Notification دادن از سمت لایه ی ViewModel به سمت لایه ی View نیازی نیست دیگه ؟
نه. اگر View بخواد از تغییری در سمت ViewModel (که بخاطر تغییری در Model رخ میده) مطلع بشه خود Binding با PropertyChanged ازش مطلع شده و View رو به روز می کنه.
پس چرا در عکس بالا ، برای ارتباط برقرار کردنِ ViewModel با View ، از Notification استفاده شده (که لایه ی ViewModel به لایه ی View ، برای ارتباط برقرار کردن ، Notification میفرسته) ؟
وقتی binding انجام میشه ، دیگه چه نیازی به Notification هست؟
ViewModel چه منبعی رو در اختیار View میذاشته؟ Students اش رو. یک مجموعه از Student ها ساخته و با مشخصه Students تحویل View داده.
و هر تغییری در مشخصه های اون تک تک اعضاء (Student) ها رخ بده با PropertyChanged ای که کلاس Student داره به View خبر میرسه و به روز میشه.
اما حالا اگر ViewModel یهو به سرش بزنه و اون مجموعه رو با یک مجموعه دیگه عوض کنه، مقدار مشخصه Students اش تغییر کرده، اما بجز خودش کدوم شیء خارجی خبر داره؟ هیچ شیء ای. View از کجا با خبر بشه که ViewModel مقدار مشخصه ای داخل خودش رو تغییر داده؟
میگه که اگه میخوایم ViewModel با View ، بایندینگِ دو طرفه انجام بده ، لایه ی ViewModel باید اینترفیسِ INotifyPropertyChanged را پیاده سازی کنه .
خوب چرا و چه نیازی هست وقتی که binding انجام میشه؟ یا باید بایندینگ انجام بشه یا باید Notify بدیم دیگه . معنای خاصی نداره هم بایندینگ کنیم و هم Notify بدیم .
Binding که علم غیب نداره. اگر مقدار مشخصه ای تغییر کنه باید به نحوی به Binding اطلاع داده بشه، وگرنه Binding تو set مشخصه که کد اضافه نکرده که بتونه بفهمه تغییری رخ داده. کد مشخصه Students رو ببینید، یک مشخصه ساده است، چیزی در set اش نداره که به یک موجودیت خارجی بتونه تغییر رو اطلاع بده. Binding از کجا بفهمه که این مشخصه مقدارش رو تغییر میده؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله.

Notification ارتباط برقرار نمی کنه، همانطور که خودتون گفتید صرفا اطلاع رسانی است. برای همین هیچ وابستگی ای از هیچ سمتی بوجود نمیاره. شیء Model صرفا به هر موجودیتی که به رخداد PropertyChanged اش متدی متصل کرده اطلاع میده که مقدار مشخصه فلان من در این لحظه تغییر کرد. رخ دادن این رخداد وابستگی نیست.

سلام استاد .
خیلی ممنون استاد :rose:
بله ، منظور منم همین بوده .

چنین چیزی نداریم. ViewModel فقط رابط ئه، خودش چیزی نداره که بخواد در Model منعکس بشه. کدوم پروپرتی ها اش؟
فرضا Student یک مشخصه به نام FirstName داره، مرجع FirstName در کل برنامه همین Student ئه، داده ها از اشیاء Student میان.
مقدار FirstName از مشخصه Student خونده و نوشته میشه. اگر FirstName تغییر کنه در خود Student اتفاق افتاده، خودش انجام دهنده تغییر ئه، برای همین Student ئه که به بقیه اطلاع میده که این مقدار تغییر کرد. سایر اشیاء بیان بهش بگن مقدار مشخصه ات تغییر کرده و خبر نداری؟ همچین وضعیتی نداریم. میشه FirstName تغییر کنه و Student بی خبر باشه؟

منظور اینه که تغییراتی که در سمت View بوجود اومده و بخاطرش داده ای باید تغییر کنه توسط ViewModel به Model منتقل میشه تا Model داده رو در منبعی که باهاش در ارتباط ئه ثبت کنه و به روز بشه. ما نمیدونیم منبع داده اون Model چیه، ممکنه یک بانک اطلاعاتی در سروری اون سر دنیا باشه یا نتیجه یک پردازش محاسباتی.
فرضا در TextBox ای مقداری تغییر می کنه که با Binding به FirstName متصل ئه. اون ViewModel رابطی بین FirstName در Student و اون TextBox ئه. پس باید به Student مقدار جدید TextBox رو برسونه تا مقدار مشخصه FirstName عوض بشه.

نه.

استاد ، احتمالا من بد سئوال را مطرح کردم .
بد مطرح کردنِ سئوالم باعث شده که بخشی از جواب سئوالِ اولم ، توی جواب دوم تونه و ... .
الان من در سئوال اولم این را پرسیده بودم :

1) حالا اگه بخوایم تغییر پروپرتیِ لایه ی ViewModel را به پروپرتیِ های لایه ی Model مخابره کنیم (تا مقادیرِ پروپرتی های لایه ی Model ، همون مقدارِ پروپرتیِ لایه ی ViewModel بشن) ، آیا باز توسط Notification ها باید این کار را کنیم؟

و در بخشی از سئوال دومم :
2) منظور از "ViewModel Update the Model" که در عکس بالا برای ارتباط برقرار کردنِ لایه ی ViewModel با لایه ی Model هست.

خوب ، این دو تا ، در واقع یک مفهوم هستن .
در واقع جوابِ زیری که برای سئوال 2 دادید :

"منظور اینه که تغییراتی که در سمت View بوجود اومده و بخاطرش داده ای باید تغییر کنه توسط ViewModel به Model منتقل میشه تا Model داده رو در منبعی که باهاش در ارتباط ئه ثبت کنه و به روز بشه. ما نمیدونیم منبع داده اون Model چیه، ممکنه یک بانک اطلاعاتی در سروری اون سر دنیا باشه یا نتیجه یک پردازش محاسباتی.
فرضا در TextBox ای مقداری تغییر می کنه که با Binding به FirstName متصل ئه. اون ViewModel رابطی بین FirstName در Student و اون TextBox ئه. پس باید به Student مقدار جدید TextBox رو برسونه تا مقدار مشخصه FirstName عوض بشه."


این جواب تون ، در واقع همون متن این دو سئوالم بود (چون من بد طرح کردم) .
یعنی میدونم که فرضا یه TextBox ای در View داریم که متناظرش ، یه پروپرتی در ViewModel داریم که اطلاعاتِ این TextBox را میخوایم بدیم به پروپرتیِ ViewModel مون تا ViewModel مون این اطلاعات را برسونه به دست پروپرتیِ متناظرش در Model .
یعنی میدونم که : ViewModel ، رابطی بین FirstName در Student و اون TextBox ئه. پس باید به Student مقدار جدید TextBox رو برسونه تا مقدار مشخصه FirstName عوض بشه.

از طرفی هم میدونم که پروپرتی های View با ViewModel ، بصورت binding ارتباط برقرار میکنن .
تا اینجا تونستم منظورم را بهتون برسونم؟

خوب ، حالا ViewModel مون ، چجوری (این اطلاعاتی را که توسط binding کردن ، از View دریافت کرد) را به دست پروپرتیِ مورد نظرش در Model میرسونه؟ آیا ViewModel ، توسط Notification ، به Model اطلاع میده؟ چون بین ViewModel و Model که binding انجام نمیدن . یعنی این ارتباط برقرار کردنِ ViewModel با Model (در صورتی که ViewModel بخواد اطلاعاتی را به Model برسونه) ، آیا از طریق Notification هست یا از طریق binding یا از طریق های دیگه ای؟
اگه از طریق های دیگه ای هست ، اونها چه طریقی هستند؟

نمیدونم تونستم منظورم را برسونم یا نه؟ (اگه تونستم ، اینها ، همون مجموع سئوال 1 و 2 ام هستن) .


بله.

نه. اگر View بخواد از تغییری در سمت ViewModel (که بخاطر تغییری در Model رخ میده) مطلع بشه خود Binding با PropertyChanged ازش مطلع شده و View رو به روز می کنه.

ViewModel چه منبعی رو در اختیار View میذاشته؟ Students اش رو. یک مجموعه از Student ها ساخته و با مشخصه Students تحویل View داده.
و هر تغییری در مشخصه های اون تک تک اعضاء (Student) ها رخ بده با PropertyChanged ای که کلاس Student داره به View خبر میرسه و به روز میشه.

چجوری شد؟!
PropertyChanged که در لایه ی Model بود که اصلا قرار نبود با View رابطه ی مستقیمی داشته باشه . این رابط را ViewModel میخواست انجام بده که.
(هر چند در مثال اون سایت هم PropertyChanged ای که در Model تعریف شد ، در هیچ لایه ی دیگه ازش استفاده نشد و رویداد PropertyChanged اش را متصل نکردن .)

اما حالا اگر ViewModel یهو به سرش بزنه و اون مجموعه رو با یک مجموعه دیگه عوض کنه، مقدار مشخصه Students اش تغییر کرده، اما بجز خودش کدوم شیء خارجی خبر داره؟ هیچ شیء ای. View از کجا با خبر بشه که ViewModel مقدار مشخصه ای داخل خودش رو تغییر داده؟

آها . یعنی مثلا اگه کالکشن باشه ، نیاز به Notification هست؟ تا وقتی شیِ کلِ کالکشن تغییر میکنه ، مطلع بشه؟
اما وقتی که مثلا دو پروپرتی از یک نوع (بدون اینکه از نوع کالکشن باشن . مثلا هر دو از نوع string باشن) را در View و ViewModel بخوایم با binding بصورت دو طرفه متصل کنیم ، نیاز به Notification از طرف ViewModel به View نیست؟

کلا یه کم گیج شدم.

Binding که علم غیب نداره. اگر مقدار مشخصه ای تغییر کنه باید به نحوی به Binding اطلاع داده بشه، وگرنه Binding تو set مشخصه که کد اضافه نکرده که بتونه بفهمه تغییری رخ داده. کد مشخصه Students رو ببینید، یک مشخصه ساده است، چیزی در set اش نداره که به یک موجودیت خارجی بتونه تغییر رو اطلاع بده. Binding از کجا بفهمه که این مشخصه مقدارش رو تغییر میده؟

اگه مقدار مشخصه ای تغییر کنه ، باید به Binding اطلاع بده؟
پس چطور وقتی پروپرتیِ یه کنترل و المنت ای را به پروپرتیِ مد نظر خودمون در المنت دیگه بصورت binding متصل میکنیم ، با تغییر مقدارِ پروپرتیِ source مون ، پروپرتیِ target هم مقدارش تغییر میکنه؟
البته من binding را برای پروپرتی ای که خدمون نوشته باشیم را نمیدونم تست کردم یا نه ولی اگه اشتباه نکنم تست کرده بودم و مشکلی نداشت .

یعنی میگید از طرفِ پروپرتیِ source ، به بایندینگ ، اطلاع داده میشه؟
من دقیق متوجه نشدم.

تشکر استاد :rose:
 

the_king

مدیرکل انجمن
1) حالا اگه بخوایم تغییر پروپرتیِ لایه ی ViewModel را به پروپرتیِ های لایه ی Model مخابره کنیم (تا مقادیرِ پروپرتی های لایه ی Model ، همون مقدارِ پروپرتیِ لایه ی ViewModel بشن) ، آیا باز توسط Notification ها باید این کار را کنیم؟
باز هم تکرار می کنم. پروپرتی ای در لایه ViewModel نیست که برای اجرای چندین موردی دنبال راهکار باشید. اون نمونه کد رو که دارید.
یک مثال از StudentViewModel و StudentView و Student بزنید که چه تغییری در کجا میتونه رخ بده که منجر به تغییر مشخصه فلان در StudentViewModel بشه که به Student مربوطه.

2) منظور از "ViewModel Update the Model" که در عکس بالا برای ارتباط برقرار کردنِ لایه ی ViewModel با لایه ی Model هست.

خوب ، این دو تا ، در واقع یک مفهوم هستن .
یک مفهوم نیستند. اولی اینه که شما مثلا مشخصه Students رو در StudentViewModel رو تغییر بدهید، یعنی شیء ObservableCollection اش رو با یک شیء ObservableCollection دیگه تعویض کنید، این چه تاثیری روی Student ها داره؟ هیچی، مقدار Student ها هیچ تغییری نمی کنه.
اما مفهوم دوم اینه که در StudentView مقدار TextBox ای تغییر کنه و مقدار از طریق StudentViewModel به تغییر مشخصه ای در Student ای منجر بشه. در دومی چه چیزی در StudentViewModel تغییر کرده؟ هیچی. در StudentViewModel مشخصه Students تغییر کرده؟ خیر.
شما اگر در فرم رنگ زمینه یک کنترل در Controls رو تغییر بدهید اون مشخصه Controls تغییر کرده؟ داخل مشخصه Controls فرم یک کنترل جدید اضافه کنید مقدار مشخصه Controls تغییر می کنه؟ یک مقدار جدید دیگه میشه؟

در واقع جوابِ زیری که برای سئوال 2 دادید :

"منظور اینه که تغییراتی که در سمت View بوجود اومده و بخاطرش داده ای باید تغییر کنه توسط ViewModel به Model منتقل میشه تا Model داده رو در منبعی که باهاش در ارتباط ئه ثبت کنه و به روز بشه. ما نمیدونیم منبع داده اون Model چیه، ممکنه یک بانک اطلاعاتی در سروری اون سر دنیا باشه یا نتیجه یک پردازش محاسباتی.
فرضا در TextBox ای مقداری تغییر می کنه که با Binding به FirstName متصل ئه. اون ViewModel رابطی بین FirstName در Student و اون TextBox ئه. پس باید به Student مقدار جدید TextBox رو برسونه تا مقدار مشخصه FirstName عوض بشه."


این جواب تون ، در واقع همون متن این دو سئوالم بود (چون من بد طرح کردم) .
دو تا مساله متفاوته. با تغییر اون TextBox هیچ تغییری در مشخصه کذایی Students اون ViewModel نمی افته. مشخصه های ViewModel چه ربطی داره به تغییر در مقدار FirstName
یعنی میدونم که فرضا یه TextBox ای در View داریم که متناظرش ، یه پروپرتی در ViewModel داریم که اطلاعاتِ این TextBox را میخوایم بدیم به پروپرتیِ ViewModel مون تا ViewModel مون این اطلاعات را برسونه به دست پروپرتیِ متناظرش در Model .
نه. متناظرش در ViewModel مشخصه ای ندارید، کدش رو که دارید. کدوم مشخصه در ViewModel متناظر اون TextBox ئه؟ در ViewModel که یک مشخصه بیشتر تعریف نشده که اونم نوع اش شباهتی به string نداره.

یعنی میدونم که : ViewModel ، رابطی بین FirstName در Student و اون TextBox ئه. پس باید به Student مقدار جدید TextBox رو برسونه تا مقدار مشخصه FirstName عوض بشه.
درسته.
از طرفی هم میدونم که پروپرتی های View با ViewModel ، بصورت binding ارتباط برقرار میکنن .
تا اینجا تونستم منظورم را بهتون برسونم؟
بله. ولی در مورد تغییر مقدار مشخصه ها و جهتی که تغییرات رخ میده مشکل دارید.
خوب ، حالا ViewModel مون ، چجوری (این اطلاعاتی را که توسط binding کردن ، از View دریافت کرد) را به دست پروپرتیِ مورد نظرش در Model میرسونه؟ آیا ViewModel ، توسط Notification ، به Model اطلاع میده؟ چون بین ViewModel و Model که binding انجام نمیدن . یعنی این ارتباط برقرار کردنِ
نه. اولا Notification برای اطلاع دادن اینه که تغییری رخ داده، نه اینکه بگه لطفا تغییرش بده. اگر FirstName تغییر کنه دیگه Student بروز شده، دیگه اطلاع رسانی به Student معنی نمیده. ViewModel هم مجموعه اشیاء Student ها رو داره و هم اسم مشخصه ای که باید تغییر کنه میدونه، پس راحت تغییرش میده، دلیلی نداره به Student اطلاع بده که حواست باشه که میخوام تغییر بدم یا تغییر بده و بعد بگه تغییر دادم ها.
تغییر چطوری رخ میده؟ با اجرا شدن set در Student. وقتی ViewModel مقدار مشخصه رو بخواد در شیء فلان عوض کنه کد set در خود Student اجرا میشه، عامل خارجی که نیست. set داخل خود کلاس Student ئه، بی خبر از تغییر نمیمونه.
ViewModel با Model (در صورتی که ViewModel بخواد اطلاعاتی را به Model برسونه) ، آیا از طریق Notification هست یا از طریق binding یا از طریق های دیگه ای؟
کد کلاس اش رو ببینید، Student ها رو داره، هر تغییر بخواد روی اشیاء Student بده از طریق مشخصه ها است، و تغییر دهنده مقدار set ئه، Student خودش تغییر دهنده است، به خودش که لازم نیست تغییر رو اطلاع بده.
چجوری شد؟!
PropertyChanged که در لایه ی Model بود که اصلا قرار نبود با View رابطه ی مستقیمی داشته باشه . این رابط را ViewModel میخواست انجام بده که.
(هر چند در مثال اون سایت هم PropertyChanged ای که در Model تعریف شد ، در هیچ لایه ی دیگه ازش استفاده نشد و رویداد PropertyChanged اش را متصل نکردن .)
ارتباط شون که مستقیم نیست، بین شون ViewModel ئه. اتصال به این مشخصه ها رو Binding مدیریت می کنه.
آها . یعنی مثلا اگه کالکشن باشه ، نیاز به Notification هست؟ تا وقتی شیِ کلِ کالکشن تغییر میکنه ، مطلع بشه؟
در این مثال بله، اما در کل اینکه Collection باشه یا نباشه مهم نیست، مهم اینه که مقدار مشخصه تغییر کنه، مقدار مشخصه.
set اجرا بشه، یا متغیر پشتی اون get تغییر کنه، وگرنه اینکه تغییرات داخل شیء رخ بده که تاثیری نداره.
اینکه داخل یک شیء اعضاء رو تغییر بدهید که خود اون شیء تغییری نمی کنه، همونه که بود. x.item رو که تغییر بدهید x عوض نمیشه.
اما وقتی که مثلا دو پروپرتی از یک نوع (بدون اینکه از نوع کالکشن باشن . مثلا هر دو از نوع string باشن) را در View و ViewModel بخوایم با binding بصورت دو طرفه متصل کنیم ، نیاز به Notification از طرف ViewModel به View نیست؟
چرا. ربطی به نوع داده اش نداره ها. وقتی مقدار یک مشخصه عوض شد (فرضا فیلد پشتی اش تغییر کرد یا شرایط محاسبه اش تغییر کرد)، همینطوری بی هیچ دلیلی که اون یکی طرف خبردار نمیشه. اینکه تغییرات اطلاع داده بشه یک مکانیسم میخواد، همینطوری که نمیشه.
اگه مقدار مشخصه ای تغییر کنه ، باید به Binding اطلاع بده؟
پس چطور وقتی پروپرتیِ یه کنترل و المنت ای را به پروپرتیِ مد نظر خودمون در المنت دیگه بصورت binding متصل میکنیم ، با تغییر مقدارِ پروپرتیِ source مون ، پروپرتیِ target هم مقدارش تغییر میکنه؟
به این دلیل که وقتی مقدار مشخصه میخواد تغییر کنه، در set اش نمیاد مقدار یک فیلد رو تغییر بده که برای تغییرش اطلاع رسانی نمیشه، با یک DependencyProperty کار می کنه که بصورت عمومی ثبت شده.
یعنی میگید از طرفِ پروپرتیِ source ، به بایندینگ ، اطلاع داده میشه؟
بله.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلامی مجدد استاد
خیلی ممنون از توضیح مفصل تون

راستی استاد ، درون لایه ی View، از (کلاسی که درون) لایه ی ViewModel شی میسازیم . و از درون کلاس لایه ی ViewModel ، از کلاسی که در لایه ی Model هست ، شی میسازیم .
من یه لحظه قاتی کردم و فکر میکردم نیازه که بصورت مستقیم ، برای ارتباط برقرار کردن با لایه ی ViewModel ، لازمه که درون Model هم شی بسازیم .
و همچنین ، همونطور که گفتید ، وقتی شیِ Model ای که درون کلاسِ ViewModel هست را ساختیم ، با تغییرِ مقادیر پروپرتی های شیِ Model از درون ViewModel ، خوب با بخشِ set ئه پروپرتی های Model ، میتونیم با خبر بشیم و نیاز به Notification از لایه ی ViewModel به لایه ی Model نیست .
هیچ چی کلا این تیکه را متوجه شدم .

-----------------------------------------

به قول خودتون یه مثال بزنم ، همه چیز بهتر باز میشه (به قول شاعر دو صد گفته چون نیم کردار نیست :) )
پروژه ی mvvm را در این پست پیوست کردم .

چک میکنین که این روش mvvm ای که در پروژه انجام دادم ، درسته یا نه؟
منظورم binding ای که برای TextBox ها به مسیر Student.FirstName و Student.LastName متصل کردم هست (که درسته یا نه)؟

یعنی این نوع binding ای که انجام دادم ، باعث ارتباط بین لایه ی View و Model نمیشه؟ (که مثلا اگه باعث ارتباط بشه ، باعث بشه کل قضیه ی mvvm که میخواد مانع از این ارتباط بشه را نقض میکنه) .

من مسیر را بجای Student.FirstName و Student.LastName ، مقدارِ FirstName و LastName که میذاشتم ، ارور میداد که نمیتونه مسیر را پیدا کنه که برای من جای تعجب نبود و این انتظار را داشتم .
اما بنابراین متوجه نشدم که چطور در اون مثالی که لینک داده بودم ، طرف ، مستقیما اومد FirstName و LastName را نوشت! (حالا میگم . من مثالِ اون طرف را هنوز چک نکردم که ببینم درست هست یا نه و اروری میده یا نه) .

تشکر استاد :rose:
 

پیوست ها

  • MVVM_Practies.rar
    52.6 کیلوبایت · بازدیدها: 1

the_king

مدیرکل انجمن
سلامی مجدد استاد
خیلی ممنون از توضیح مفصل تون

راستی استاد ، درون لایه ی View، از (کلاسی که درون) لایه ی ViewModel شی میسازیم . و از درون کلاس لایه ی ViewModel ، از کلاسی که در لایه ی Model هست ، شی میسازیم .
من یه لحظه قاتی کردم و فکر میکردم نیازه که بصورت مستقیم ، برای ارتباط برقرار کردن با لایه ی ViewModel ، لازمه که درون Model هم شی بسازیم .
و همچنین ، همونطور که گفتید ، وقتی شیِ Model ای که درون کلاسِ ViewModel هست را ساختیم ، با تغییرِ مقادیر پروپرتی های شیِ Model از درون ViewModel ، خوب با بخشِ set ئه پروپرتی های Model ، میتونیم با خبر بشیم و نیاز به Notification از لایه ی ViewModel به لایه ی Model نیست .
هیچ چی کلا این تیکه را متوجه شدم .

-----------------------------------------

به قول خودتون یه مثال بزنم ، همه چیز بهتر باز میشه (به قول شاعر دو صد گفته چون نیم کردار نیست :) )
پروژه ی mvvm را در این پست پیوست کردم .

چک میکنین که این روش mvvm ای که در پروژه انجام دادم ، درسته یا نه؟
کدتون معماری MVVM نداره و مستقیم هم بین Model و View ارتباط برقرار کرده اید.

منظورم binding ای که برای TextBox ها به مسیر Student.FirstName و Student.LastName متصل کردم هست (که درسته یا نه)؟
Binding مشکلی نداره، چون مادامی که DataContext رو در StudentViewControl_Loaded مشخص نکرده اید View نمیدونسته که Student.FirstName چیه.
اما در Button_Click صریحا به Model.Student.FirstName مقدار داده اید، Button_Click بدون اینکه با کلاس Student ارتباط برقرار کنه کامپایل شدنی بود؟

یعنی این نوع binding ای که انجام دادم ، باعث ارتباط بین لایه ی View و Model نمیشه؟ (که مثلا اگه باعث ارتباط بشه ، باعث بشه کل قضیه ی mvvm که میخواد مانع از این ارتباط بشه را نقض میکنه) .
فرض کنیم که بخش Button_Click رو ننوشته بودید.
موقعی که دارید View رو طراحی می کنید یک Binding برای Student.FirstName نوشته اید که نه مشخصه Student چیه و نه FirstName
یعنی اگر عوضش کنید و بجایش MyStudent.MyFirstName هم بنویسید خطا نمی گیره که این Path چیه.
پس بعدا DataContext میتونسته هر موجودیتی باشه که Student.FirstName داره، وابسته به اون مشخصه FirstName در کلاس Student و خود کلاس Student نیست.
شما بعدا این Binding رو در زمان دیگری در Window_Loaded با مشخص کردن DataContext به StudentViewModel ربط می دهید.
اما اومده اید داخل Button_Click صریحا با FirstName در کلاس Student ارتباط برقرار کرده اید. در اون کد مثال اسمی از Student در View بود؟
من مسیر را بجای Student.FirstName و Student.LastName ، مقدارِ FirstName و LastName که میذاشتم ، ارور میداد که نمیتونه مسیر را پیدا کنه که برای من جای تعجب نبود و این انتظار را داشتم.

اما بنابراین متوجه نشدم که چطور در اون مثالی که لینک داده بودم ، طرف ، مستقیما اومد FirstName و LastName را نوشت! (حالا میگم . من مثالِ اون طرف را هنوز چک نکردم که ببینم درست هست یا نه و اروری میده یا نه) .
مستقیم نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کدتون معماری MVVM نداره و مستقیم هم بین Model و View ارتباط برقرار کرده اید.

سلامی مجدد
خیلی ممنون استاد (همینطور ممنون از بقیه ی قسمت های جواب تون) .

الان استاد اون کد را باید چطور تغییر بدم که معماری mvvm پیدا کنه؟
درک من از mvvm ، اون کدی بود که اون طور نوشتم .
هر جور دیگه ای که نوشتم (که مثلا بخوام شبیه اون کدی که در اون لینک از آموزش دادم بشه) ، ارور میداد و ... .


Binding مشکلی نداره، چون مادامی که DataContext رو در StudentViewControl_Loaded مشخص نکرده اید View نمیدونسته که Student.FirstName چیه.
اما در Button_Click صریحا به Model.Student.FirstName مقدار داده اید، Button_Click بدون اینکه با کلاس Student ارتباط برقرار کنه کامپایل شدنی بود؟


فرض کنیم که بخش Button_Click رو ننوشته بودید.
موقعی که دارید View رو طراحی می کنید یک Binding برای Student.FirstName نوشته اید که نه مشخصه Student چیه و نه FirstName
یعنی اگر عوضش کنید و بجایش MyStudent.MyFirstName هم بنویسید خطا نمی گیره که این Path چیه.
پس بعدا DataContext میتونسته هر موجودیتی باشه که Student.FirstName داره، وابسته به اون مشخصه FirstName در کلاس Student و خود کلاس Student نیست.
شما بعدا این Binding رو در زمان دیگری در Window_Loaded با مشخص کردن DataContext به StudentViewModel ربط می دهید.

اما اومده اید داخل Button_Click صریحا با FirstName در کلاس Student ارتباط برقرار کرده اید. در اون کد مثال اسمی از Student در View بود؟


منظورتون اینه که binding ای که توی کد xaml برای textbox ها (به پروپرتیِ Student.FirstName) و همچنین datacontext ای که توی window_load مشخص کردم ، مشکلی از لحاظ معماری mvvm نداره ولی مشکل برای این معماری ، از جایی شروع در رویداد button_click ، مقدارِ شیِ StudentViewModel.Student.FirstName را تغییر دادم؟

اگه منظورتون اینه ، پس برای تغییر پروپرتیِ StudentViewModel.Student.FirstName باید چجوری انجام بدم؟

تشکر استاد .
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد (همینطور ممنون از بقیه ی قسمت های جواب تون) .

الان استاد اون کد را باید چطور تغییر بدم که معماری mvvm پیدا کنه؟
درک من از mvvm ، اون کدی بود که اون طور نوشتم .
هر جور دیگه ای که نوشتم (که مثلا بخوام شبیه اون کدی که در اون لینک از آموزش دادم بشه) ، ارور میداد و ... .
ساده ترین پیشنهادم اینه، عین همون مثال رو بنویسید که بدون مشکل کامپایلش می کنه و بعد تغییرش بدهید، ساختن فولدر View رو هم فراموش نکنید.

منظورتون اینه که binding ای که توی کد xaml برای textbox ها (به پروپرتیِ Student.FirstName) و همچنین datacontext ای که توی window_load مشخص کردم ، مشکلی از لحاظ معماری mvvm نداره ولی مشکل برای این معماری ، از جایی شروع در رویداد button_click ، مقدارِ شیِ StudentViewModel.Student.FirstName را تغییر دادم؟
بله، Binding ای که نوشته اید با مشخصه Student اون ViewModel تون کار داره، نه کلاس Student، پس وابستگی به Model نداره.
اون View هم صرف نظر از button_click به کلاس Student وابستگی نداره، اون button_click کار رو خراب کرده.
اگه منظورتون اینه ، پس برای تغییر پروپرتیِ StudentViewModel.Student.FirstName باید چجوری انجام بدم؟
mvvm.png

در نمودار هست. Data Binding و Commands . مطلبی که لینکش رو دادید نخوندید، در همون لینک در مورد نحوه نوشتن Command توضیح داده بود.
در نظر بگیرید که معماری MVVM در WPF با استفاده از Data Binding بنا شده که در زمان اجرا ارزیابی میشه، نه زمان کامپایل، تا بتونه بدون وابستگی ارتباط بین دو موجودیت رو پیاده سازی کنه. قراره دو موجودیت مستقل باشند، با هم ارتباط داشته باشند ولی بهم وابسته نباشند. بشه یکی شون رو با یک موجودیت دیگه تعویض کرد، بدون اینکه در طرف مقابل نیاز به تغییر خاصی باشه. در مثال می بینید که کل توصیف طرف ارتباط در یک DataContext بود، با تغییر DataContext در یک لحظه طرف ارتباط تغییر می کنه.

باید بشه View رو با یک View دیگه عوض کرد، بشه ViewModel رو با یک ViewModel دیگه عوض کرد. عدم وابستگی یعنی در Path یک FirstName داشته باشید که در زمان کامپایل هنوز معلوم نیست قراره مربوط به چی ViewModel ای باشه. Data Binding برای پیاده سازی چنین چیزی مناسبه، نه کدی که صریحا دنبال کلاس StudentViewModel ای میگرده.

 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ساده ترین پیشنهادم اینه، عین همون مثال رو بنویسید که بدون مشکل کامپایلش می کنه و بعد تغییرش بدهید، ساختن فولدر View رو هم فراموش نکنید.


بله، Binding ای که نوشته اید با مشخصه Student اون ViewModel تون کار داره، نه کلاس Student، پس وابستگی به Model نداره.
اون View هم صرف نظر از button_click به کلاس Student وابستگی نداره، اون button_click کار رو خراب کرده.

mvvm.png

در نمودار هست. Data Binding و Commands . مطلبی که لینکش رو دادید نخوندید، در همون لینک در مورد نحوه نوشتن Command توضیح داده بود.
در نظر بگیرید که معماری MVVM در WPF با استفاده از Data Binding بنا شده که در زمان اجرا ارزیابی میشه، نه زمان کامپایل، تا بتونه بدون وابستگی ارتباط بین دو موجودیت رو پیاده سازی کنه. قراره دو موجودیت مستقل باشند، با هم ارتباط داشته باشند ولی بهم وابسته نباشند. بشه یکی شون رو با یک موجودیت دیگه تعویض کرد، بدون اینکه در طرف مقابل نیاز به تغییر خاصی باشه. در مثال می بینید که کل توصیف طرف ارتباط در یک DataContext بود، با تغییر DataContext در یک لحظه طرف ارتباط تغییر می کنه.

باید بشه View رو با یک View دیگه عوض کرد، بشه ViewModel رو با یک ViewModel دیگه عوض کرد. عدم وابستگی یعنی در Path یک FirstName داشته باشید که در زمان کامپایل هنوز معلوم نیست قراره مربوط به چی ViewModel ای باشه. Data Binding برای پیاده سازی چنین چیزی مناسبه، نه کدی که صریحا دنبال کلاس StudentViewModel ای میگرده.


خیلی ممنون استاد .
لطف کردین . :rose:

آها ، پس قضیه ی ارتباطِ View با ViewModel ، باید توسط Command ها انجام بشه . درسته؟
(البته منظورم حالتِ برعکسش نیست . یعنی ارتباطِ ViewModel با View نیست که این حالت ، توسط binding انجام میشه . هر چند بایندینگ دو طرفه هم میشه انجام داد) .
پس دنبالِ روش های تغییر شی بصورت عادی و صریح (یعنی مثلا تغییر شیِ StudentViewModel.Student.FirstName بصورت صریح) نباید برم و بجاش تغییر شی را از دستورات Command ها باید پیش ببرم. درسته؟
البته من الان قضیه ی Command ها را نمیدونم و باید بعدا سر فرصت کامل بررسی شون کنم .


ولی من استاد هنوز یه چیز را درک نکردم .
اینکه وقتی پروپرتیِ Student.FirstName را به پروپرتیِ Text ئه TextBox بایندینگ کردم ، خوب نهایتا پروپرتیِ Student ، شی از از نوعِ کلاسِ Student هست و FirstName هم عضوی از کلاس Student هست . هنوز متوجه نشدم که چرا این با اونکه به پروپرتی ای از عضو Student ، بایندینگ میکنه ، مشکلی نداره از لحاظ معماری mvvm اما چرا وقتی مقدار پروپرتیِ StudentViewModel.Student.FirstName را تغییر میدم ، از لحاظ این معماری اشکال داره؟!
چون هر دو که با یک پروپرتی از یک کلاس کار دارن (حالا یکی به این پروپرتی ، بایندینگ انجام میده اما یکی دیگه ، مقدار این پروپرتی را عوض میکنه) .
نمیدونم تونستم منظورم را برسونم یا نه؟

تشکر استاد
 

the_king

مدیرکل انجمن
خیلی ممنون استاد .
لطف کردین . :rose:

آها ، پس قضیه ی ارتباطِ View با ViewModel ، باید توسط Command ها انجام بشه . درسته؟
Data Binding و Commands
پس دنبالِ روش های تغییر شی بصورت عادی و صریح (یعنی مثلا تغییر شیِ StudentViewModel.Student.FirstName بصورت صریح) نباید برم و بجاش تغییر شی را از دستورات Command ها باید پیش ببرم. درسته؟
اگر بخواهید با الگوی طراحی MVVM پیش بروید باید از هر کدی شبیه به اون چیزی که نوشتید اجتناب کنید.
البته من الان قضیه ی Command ها را نمیدونم و باید بعدا سر فرصت کامل بررسی شون کنم .


ولی من استاد هنوز یه چیز را درک نکردم .
اینکه وقتی پروپرتیِ Student.FirstName را به پروپرتیِ Text ئه TextBox بایندینگ کردم ، خوب نهایتا پروپرتیِ Student ، شی از از نوعِ کلاسِ Student هست و FirstName هم عضوی از کلاس Student هست . هنوز متوجه نشدم که چرا این با اونکه به پروپرتی ای از عضو Student ، بایندینگ میکنه ، مشکلی نداره از لحاظ معماری mvvm اما چرا وقتی مقدار پروپرتیِ StudentViewModel.Student.FirstName را تغییر میدم ، از لحاظ این معماری اشکال داره؟!
FirstName عضوی از کلاس Student هست، اما FirstName اون Binding که الزاما هدفش Student.FirstName نیست.
امتحان کنید، یک کلاس جدید شبیه Student که FirstName داشته باشه و یک کلاس جدید شبیه StudentViewModel بسازید که با اون کلاس جدید کار کنه و موقع کلیک روی یک دکمه شبیه اون کدی که در StudentViewControl_Loaded بود DataContext رو تغییر بدهید. کار می کنه. پس نمی توانید بگید FirstName ئه همون Student.FirstName ئه. بهش وابسته نیست، مستقل ئه. ممکنه با ده جور ViewModel دیگه سازگار باشه.
این View به Model وابستگی نداره.
در MVVM قراره بخش های View و Model مستقل و مجزایی وجود داشته باشه. مستقل بودن یعنی چی؟ یعنی ماهیت شون بهم وابسته نباشه.
در اون button_Click شما View رو وابسته می کنید به کلاس Student در Model. بدون وجود اون Model اون View تون تعریف اش ناقصه.
چون هر دو که با یک پروپرتی از یک کلاس کار دارن (حالا یکی به این پروپرتی ، بایندینگ انجام میده اما یکی دیگه ، مقدار این پروپرتی را عوض میکنه) .
نمیدونم تونستم منظورم را برسونم یا نه؟
اگر Class هدف Binding مشخص باشه پس با کلاس دیگری جز اون کلاس نمی تونه کار کنه. نمیشه که بگید این Binding هدفش کلاس Student ئه ولی با این وجود بجای Student کلاس دیگری رو بکار ببرید و مشکلی پیش نیاد. چطوری میتونه با کلاس Student2 هم کار کنه اگر هدفش Student ئه؟
اگر توانستید اون Binding رو برای ارتباط با کلاس دیگری بجز اون Student بکار ببرید که می توانید، معنی اش اینه که فرض تون اشتباه بوده و کلاس هدف x یا y یا کلا هر ساختار ثابت و مشخصی نیست. استقلال دارند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
FirstName عضوی از کلاس Student هست، اما FirstName اون Binding که الزاما هدفش Student.FirstName نیست.
امتحان کنید، یک کلاس جدید شبیه Student که FirstName داشته باشه و یک کلاس جدید شبیه StudentViewModel بسازید که با اون کلاس جدید کار کنه و موقع کلیک روی یک دکمه شبیه اون کدی که در StudentViewControl_Loaded بود DataContext رو تغییر بدهید. کار می کنه. پس نمی توانید بگید FirstName ئه همون Student.FirstName ئه. بهش وابسته نیست، مستقل ئه. ممکنه با ده جور ViewModel دیگه سازگار باشه.
این View به Model وابستگی نداره.
در MVVM قراره بخش های View و Model مستقل و مجزایی وجود داشته باشه. مستقل بودن یعنی چی؟ یعنی ماهیت شون بهم وابسته نباشه.

سلامی مجدد
خیلی ممنون استاد .
اون Path برای Binding ای که مقدارش را Student.FirstName داده بودیم ، میدونیم که به معنای این هست که در شیِ DataContext (شیِ منبع) بعد از اینکه مشخص شد ، برو دنبال پروپرتیِ Student (حالا این پروپرتیِ Student ، از هر نوعی میتونه باشه) بگرد و همچنین درونِ شیِ این پروپرتیِ Student ، دنبال پروپرتی ای با نام FirstName بگرد و این پروپرتیِ FirstName را به پروپرتیِ شیِ هدف مون binding کن .
درسته دیگه؟

حالا منظورتون این هست که در این ساختار Binding ، میشه بجای پروپرتیِ Student که درون کلاس StudentViewModel و همچنین بجای پروپرتیِ FirstName که درون کلاس Student بود ، پروپرتی هایی را دقیقا با همین نام اما در یک کلاسِ دیگه (که نام کلاس متفاوت باشه) نوشت و این Binding هم اگه شیِ DataContext اش را عوض کنیم ، در اونجا هم کار میکنه .
درست متوجه ی منظورتون شدم؟ منظورتون همینه؟

در اون button_Click شما View رو وابسته می کنید به کلاس Student در Model. بدون وجود اون Model اون View تون تعریف اش ناقصه.

اگه منظورتون همونی هست که در بالا گفتم ، خوب برای وقتی که در رویداد کلیک دکمه ، مقدار :

C#:
this.StudentViewModel.Student.FirstName = "Shahid Mohsen";

را مشخص کردیم ، در اینجا هم میشه بجای پروپرتیِ Student که درون کلاس StudentViewModel و همچنین بجای پروپرتیِ FirstName که درون کلاس Student بود ، پروپرتی هایی را دقیقا با همین نام اما در یک کلاسِ دیگه (که نام کلاس متفاوت باشه) بنویسیم و در این حالت هم کار میکنه دیگه .
نمیدونم تونستم منظورم را برسونم یا نه .


=======================================================================


Data Binding و Commands

اگر بخواهید با الگوی طراحی MVVM پیش بروید باید از هر کدی شبیه به اون چیزی که نوشتید اجتناب کنید.

الان استاد ببینید ، من تصوری که از mvvm تا اینجا پیدا کردم ، چیزی شبیه به شکل های زیر هست . ببینید درستن؟

اول این رو بگم که با ارتباط بینِ ViewModel با Model ، مشکلی ندارم و متوجه شدم .
یعنی مشکلی ندارم که در اون تصویری اومد که اگه Model میخواد با ViewModel رابطه داشته باشه ، بهش Notification میفرسته و کلا اطلاع رسانی میکنه (حالا توسط پیاده سازیِ اینترفیس INotifyPropertyChanged یا هر روش دیگه ای) و همچنین ViewModel هم برای ارتباط با Model ، کار خاصی لازم نیست کنه و مستقیما شی ای از Model (که در درون کلاس ViewModel) را که در اختیار داره را تغییر میده (که همون نوشته ی "ViewModel Update The Model" در اون تصویر هست) .
تا اینجا را درست گفتم دیگه؟




اما مسئله ی من ، ارتباطِ View با ViewModel هست .
نکته ی اساسی ای که الان متوجه شدم اینه که View اصلا نباید کارهای تغییرِ اشیا و اعضای (مثل پروپرتی هایی که در) کلاس Model را خودش تغییر بده (یعنی اون کد که برای تغییر شی در رویداد کلیک دکمه که این رویداد جزء View محسوب میشد را نباید انجام میدادم . چون مستقیما خودش اومد عضو FirstName که عضوی از کلاس Model محسوب میشد را ولو با واسطه ای از شیِ ViewModel ، تغییر داد) .

بلکه نکته ی اساسی اینجاست که هر تغییری که View اگه بخواد روی (اشیا و اعضای کلاس های) Model انجام بده ، اول اینکه خودش نباید انجام بده و دوم اینکه باید برای انجام این تغییرات (روی اشیا Model) ، باید از ViewModel درخواست کنه که این کار را براش انجام بده .
یعنی نکته ی اساسی اینجاست که اگه View بخواد با ViewModel ، ارتباط داشته باشه (منظورم رابطه ی برعکسش که ارتباطِ ViewModel با View هست ، نیست) ، باید کارهاش را با درخواست کردن پیش ببره . یعنی View ، از ViewModel ، درخواستِ انجامِ کاری را کنه که میخواد روی Model انجام بده تا ViewModel اون کار را براش انجام بده .



1) در حالت اول (این حالت ، Binding کردن را نادیده میگیریم و اصلا نمیخوایم Binding ای انجام بدیم) ، برای ارتباطِ View با ViewModel ، درخواستِ مورد نظرمون را از View به ViewModel میفرستیم تا (بصورت غیر مستقیم) ، ViewModel مون اون درخواست را برای اِعمال تغییرات (روی مقادیر اعضای Model) انجام بده .
حالا این درخواست میتونه توسط متد ، رویداد ، یا Command ها انجام بشه . یعنی شکل زیر :


1_Request.jpg


حالا این درخواست میتونه این طور باشه که مثلا متد یا رویدادی را درونِ ViewModel بنویسه که مثلا آرگومان هایی را از View بگیره (آرگومان هایی که مثلا View با فراخونیِ این متد مشخص کنه که کدوم پروپرتیِ ViewModel و همچنین چه عضوی از این پروپرتی (که این عضو ، همون عضوِ Model هست) ، چه مقدارِ جدیدی بگیره) یا اینکه این درخواست میتونه هر طورِ دیگه باشه . مثلا با ارسال رویداد باشه . حالا با command ها آشنا نیستم اما یه چیزهای سطحی که متوجه شدم ، انگار command ها هم این کار را انجام میدن . یعنی درخواستی را ارسال میکنن که کارشون شبیه رویدادهاست .

یعنی مثلا (اگه نخواستیم از command ها استفاده کنیم ، این طور هم میشه که) این متدِ درونِ ViewModel :
یه ورودی از نوع object بگیره که همون شیِ پروپرتی ای هست که درون ViewModel هست (تا ViewModel بدونه تغییراتی روی اعضای این پروپرتی میخواد اِعمال بشه . مثلِ پروپرتیِ Studentدر کلاس StudentViewModel) .
و همچنین یه ورودی دیگه حالا مثلا از نوعِ رشته که نام پروپرتی ای را بده که جزء اعضای پروپرتیِ که در آرگومان اول داده بودیم و میخواد مقدار اون پروپرتی را تغییر بده ، بده (یعنی مثلا پروپرتیِ FirstName را که میخواد مقدارش را تغییر بده ، نامِ این پروپرتی را بصورت رشته دریافت کنه) و بعد توسط Reflection ، دنبال این پروپرتی ، در شیِ آرگومان اول که داده شد ، بگرده .
و همچنین آرگومان سوم را هم object ای بگیره به عنوان مقدار . یعنی مقدارِ (FirstName ای که در آرگومان دوم بصورت رشته در این متد داده بودیم) را تغییر بده (توسط Reflection) .
یا حالا توسط Command یا هر روش دیگه ای .


2) در حالت دوم (در این حالت هم نمیخوایم Binding ای انجام بدیم) ، اگه ViewModel بخواد با View ارتباط برقرار کنه ، توسط رویداد (و یا هر روش دیگه ای شبیه به این) ، تغییراتی که برای پروپرتی هاش اتفاق افتاد را به View اطلاع رسانی میکنه . یعنی شکلی شبیه زیر (این حالت ، علاوه بر حالت قبل هست . یعنی روش قبلی که ارتباط View با ViewModel بود ، به همون روش قبلی ، سر جاش باقی هست) :


2_Request_Notify.jpg


3) حالت سوم ، حالتی هست که Binding ئه یک طرفه هم انجام میدیم . یعنی Binding ای که وقتی پروپرتیِ ViewModel تغییر کرد ، به پروپرتیِ کنترلی در View متصل میشه و اون پروپرتی از کنترل و المنت ، اتوماتیک تغییر میکنه . یعنی در این حالت ، دیگه نیاز به Notification از طرف ViewModel به View دیگه لازم نیست (و Binding این کار را انجام میده) .
همچنین ارتباطِ View با ViewModel ، مثل روشِ حالت اول هست . یعنی :


3_Request_BindingOneWay.jpg

4) حالت چهارم ، Binding اش برعکسِ حالت قبلی هست . یعنی حالتی هست که Binding ئه یک طرفه اما از طرفِ View به ViewModel انجام میگیره. یعنی Binding ای که وقتی پروپرتیِ المنتی در View تغییر کرد ، به پروپرتیِ ای در ViewModel متصل میشه و اون پروپرتی از ViewModel ، اتوماتیک تغییر میکنه .
در این حالت ، دیگه نیاز به ارسال درخواست از طرف View به ViewModel نیست (و Binding این کار را انجام میده) .
همچنین ارتباطِ View با ViewModel ، مثل روشِ حالت اول هست . یعنی :


4_Request_BindingOneWay2.jpg


5) حالت پنجم هم که Binding ئه دو طرفه هست .
در این حالت ، نه نیازی به ارسال درخواست از طرف View به ViewModel هست و نه نیازی به اطلاع رسانی از طرف ViewModel به View . چون تغییر مقدار و اینها ، اتوماتیک در دو طرف ، در Binding ئه دو طرفه ، انجام میشه .
یعنی شکل زیر :


5_BindingTwoWay.jpg

اینهایی که گفتم ، درست هستند؟
تشکر استاد :rose:
 

the_king

مدیرکل انجمن
سلامی مجدد
خیلی ممنون استاد .
اون Path برای Binding ای که مقدارش را Student.FirstName داده بودیم ، میدونیم که به معنای این هست که در شیِ DataContext (شیِ منبع) بعد از اینکه مشخص شد ، برو دنبال پروپرتیِ Student (حالا این پروپرتیِ Student ، از هر نوعی میتونه باشه) بگرد و همچنین درونِ شیِ این پروپرتیِ Student ، دنبال پروپرتی ای با نام FirstName بگرد و این پروپرتیِ FirstName را به پروپرتیِ شیِ هدف مون binding کن .
درسته دیگه؟
بله.
حالا منظورتون این هست که در این ساختار Binding ، میشه بجای پروپرتیِ Student که درون کلاس StudentViewModel و همچنین بجای پروپرتیِ FirstName که درون کلاس Student بود ، پروپرتی هایی را دقیقا با همین نام اما در یک کلاسِ دیگه (که نام کلاس متفاوت باشه) نوشت و این Binding هم اگه شیِ DataContext اش را عوض کنیم ، در اونجا هم کار میکنه .
درست متوجه ی منظورتون شدم؟ منظورتون همینه؟
بله.
اگه منظورتون همونی هست که در بالا گفتم ، خوب برای وقتی که در رویداد کلیک دکمه ، مقدار :

C#:
this.StudentViewModel.Student.FirstName = "Shahid Mohsen";

را مشخص کردیم ، در اینجا هم میشه بجای پروپرتیِ Student که درون کلاس StudentViewModel و همچنین بجای پروپرتیِ FirstName که درون کلاس Student بود ، پروپرتی هایی را دقیقا با همین نام اما در یک کلاسِ دیگه (که نام کلاس متفاوت باشه) بنویسیم و در این حالت هم کار میکنه دیگه .
اولا شما در زمان اجرا کد button_click رو نمی توانید تغییر بدهید، این تغییری که میگید قبل از زمان کامپایل ئه. شما در زمان اجرا چطوری می توانید همچین کاری رو انجام بدهید. تغییری که می خواهید فقط با ویرایش View میسر ئه، قبل از کامپایل. و صریحا دارید View ای که مشکل داره و به Model ای وابسته است رو ویرایش می کنید تا به Model دیگری وابسته باشه. میشه مثل همون که قبلا بود.

بعد از کامپایل هم View شما چه بخواهید و چه نخواهید به اون Model وابسته شده، چه ازش استفاده بکنید و چه نکنید.
چه بعدا DataContext رو تغییر بدهید و چه ندهید، View در زمان کامپایل به اون Model وابسته شده.

ثانیا وقتی شما کد رو دستکاری کنید و کد View رو تغییر می دهید، همون View قبلی است یا View جدید؟ وقتی View رو ویرایش می کنید دیگه View قبلی نیست که بگید View ای نوشتم که هم با x کار می کنه و هم با y، پس به x وابستگی نداره. شما بخش View تون رو تغییر می دهید تا دیگه به Model ئه x وابسته نباشه و بجایش به Model ئه y وابسته باشه و رضایت هم دارید که پس از ویرایش اش کار می کنه. مگر پروژه هایی که بر پایه MVVM نیستند کار نمی کنند؟ در کدی که بر پایه MVVM نباشه و یک وابستگی بین View و Model هست با تغییر و ویرایش کردن مورد وابستگی رو عوض می کنند و کد جدید هم کار می کنه، ولی همچنان بین View و Model وابستگی داره و با MVVM نمیخونه.

ثالثا این چه MVVM ای شد که در بخش View کدی هست که از کل ساختار Student در Model خبر داره؟ اگر در Model نوع داده FirstName از string به int تغییر کنه و بخش ViewModel هم متناسب با این تغییر ویرایش بشه، باید پروژه بدون مشکل کامپایل و اجرا بشه.
که در اون مثال که قبلا بررسی کردیم می کنه، یعنی Model و ModelView تغییر کرده و View دست نخورده تغییر نکرده و هیچ خطا یا اختلالی هم رخ نداده.

اما در پروژه شما جواب نمیده، چون View به Model وابسته است، به محض تغییر نوع داده FirstName به int، در View که باید مستقل باشه خطا میگیره که من نمی تونم "Shahid Mohsen" رو در FirstName قرار بدهم. در MVVM تغییر در ساختار Model به View چه ربطی داره؟

در هر صورت نه من لزومی می بینم که شما رو قانع کنم و نه اینکه درستی درک تون از MVVM رو تایید یا رد کنم. هر درکی که از MVVM دارید به خودتون مربوطه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله.

بله.

اولا شما در زمان اجرا کد button_click رو نمی توانید تغییر بدهید، این تغییری که میگید قبل از زمان کامپایل ئه. شما در زمان اجرا چطوری می توانید همچین کاری رو انجام بدهید. تغییری که می خواهید فقط با ویرایش View میسر ئه، قبل از کامپایل. و صریحا دارید View ای که مشکل داره و به Model ای وابسته است رو ویرایش می کنید تا به Model دیگری وابسته باشه. میشه مثل همون که قبلا بود.

بعد از کامپایل هم View شما چه بخواهید و چه نخواهید به اون Model وابسته شده، چه ازش استفاده بکنید و چه نکنید.
چه بعدا DataContext رو تغییر بدهید و چه ندهید، View در زمان کامپایل به اون Model وابسته شده.

ثانیا وقتی شما کد رو دستکاری کنید و کد View رو تغییر می دهید، همون View قبلی است یا View جدید؟ وقتی View رو ویرایش می کنید دیگه View قبلی نیست که بگید View ای نوشتم که هم با x کار می کنه و هم با y، پس به x وابستگی نداره. شما بخش View تون رو تغییر می دهید تا دیگه به Model ئه x وابسته نباشه و بجایش به Model ئه y وابسته باشه و رضایت هم دارید که پس از ویرایش اش کار می کنه. مگر پروژه هایی که بر پایه MVVM نیستند کار نمی کنند؟ در کدی که بر پایه MVVM نباشه و یک وابستگی بین View و Model هست با تغییر و ویرایش کردن مورد وابستگی رو عوض می کنند و کد جدید هم کار می کنه، ولی همچنان بین View و Model وابستگی داره و با MVVM نمیخونه.

ثالثا این چه MVVM ای شد که در بخش View کدی هست که از کل ساختار Student در Model خبر داره؟ اگر در Model نوع داده FirstName از string به int تغییر کنه و بخش ViewModel هم متناسب با این تغییر ویرایش بشه، باید پروژه بدون مشکل کامپایل و اجرا بشه.
که در اون مثال که قبلا بررسی کردیم می کنه، یعنی Model و ModelView تغییر کرده و View دست نخورده تغییر نکرده و هیچ خطا یا اختلالی هم رخ نداده.

اما در پروژه شما جواب نمیده، چون View به Model وابسته است، به محض تغییر نوع داده FirstName به int، در View که باید مستقل باشه خطا میگیره که من نمی تونم "Shahid Mohsen" رو در FirstName قرار بدهم. در MVVM تغییر در ساختار Model به View چه ربطی داره؟

در هر صورت نه من لزومی می بینم که شما رو قانع کنم و نه اینکه درستی درک تون از MVVM رو تایید یا رد کنم. هر درکی که از MVVM دارید به خودتون مربوطه.

خیلی ممنون استاد .
بله .
منظورم همین استدلال ها بود (که میخواستم بدونم) که تازه بیشتر متوجه شدم .

حالا استاد درباره ی اون 5 تا شکل (و حالت هایی) که گذاشتم و توضیحات شون را دادم ، برداشتم از اونها درستن؟
و اگه هر جا برداشتم اشتباه بود ، میگین کجاست؟
تشکر استاد . :rose:
 

جدیدترین ارسال ها

بالا