MVVM एप्लिकेशन में नेविगेशन को कौन नियंत्रित करना चाहिए?


33

उदाहरण # 1: मेरे पास मेरे MVVM एप्लिकेशन में प्रदर्शित दृश्य है (चर्चा के उद्देश्यों के लिए सिल्वरलाइट का उपयोग करें) और मैं एक बटन पर क्लिक करता हूं जो मुझे एक नए पृष्ठ पर ले जाना चाहिए।

उदाहरण # 2: उसी दृश्य में एक और बटन होता है, जिसे क्लिक करने पर, एक चाइल्ड विंडो (डायलॉग) में विवरण दृश्य को खोलना चाहिए।

हमें पता है कि हमारे ViewModel द्वारा कमांड ऑब्जेक्ट होंगे जो उपयोगकर्ता के क्लिक का जवाब देने वाले तरीकों के साथ बटन से बंधे होंगे। लेकिन, फिर क्या? हम कार्रवाई कैसे पूरी करेंगे? यहां तक ​​कि अगर हम एक तथाकथित नैविगेशन सर्विस का उपयोग करते हैं, तो हम इसे क्या बता रहे हैं?

अधिक विशिष्ट होने के लिए, एक पारंपरिक व्यू-प्रथम मॉडल (जैसे URL पर आधारित नेविगेशन योजनाएं जैसे वेब या SL अंतर्निहित नेविगेशन फ्रेमवर्क में) कमांड ऑब्जेक्ट्स को यह जानना होगा कि आगे क्या प्रदर्शन करना है। जब पैटर्न द्वारा प्रचारित चिंताओं के अलगाव की बात आती है तो यह रेखा पार करने लगता है।

दूसरी ओर, यदि बटन को कमांड ऑब्जेक्ट पर वायर्ड नहीं किया गया था और हाइपरलिंक की तरह व्यवहार किया गया था, तो नेविगेशन नियमों को मार्कअप में परिभाषित किया जा सकता है। लेकिन क्या हम चाहते हैं कि दृश्य अनुप्रयोग के प्रवाह को नियंत्रित करें और व्यवसाय तर्क का सिर्फ एक और प्रकार नेविगेशन न करें? (मैं कुछ मामलों में हां कह सकता हूं और दूसरों में नहीं।)

मेरे लिए, MVVM पैटर्न का यूटोपियन कार्यान्वयन (और मैंने दूसरों को इस बारे में सुना है) के लिए ViewModel को इस तरह से वायर्ड किया जाएगा कि एप्लिकेशन हेडलेस (यानी नो व्यू) चला सके। यह कोड-आधारित परीक्षण के लिए सबसे अधिक सतह क्षेत्र प्रदान करता है और दृश्य को अनुप्रयोग पर एक सच्ची त्वचा बनाता है। और मेरे ViewModel का ध्यान नहीं रखना चाहिए अगर यह मुख्य विंडो, एक फ्लोटिंग पैनल या एक चाइल्ड विंडो में प्रदर्शित हो, तो क्या यह होना चाहिए?

इस मूल्यांकन के अनुसार, यह रनटाइम में कुछ अन्य तंत्र पर निर्भर है कि प्रत्येक ViewMelel के लिए क्या दृश्य प्रदर्शित किया जाना चाहिए। लेकिन क्या होगा यदि हम एक दृश्य को कई ViewModels या इसके विपरीत साझा करना चाहते हैं?

तो View-ViewModel संबंध को प्रबंधित करने की आवश्यकता को देखते हुए, ताकि हम यह जान सकें कि बाल खिड़कियों / संवादों को प्रदर्शित करने सहित विचारों के बीच नेविगेट करने की आवश्यकता के साथ-साथ हम MVVM पैटर्न में वास्तव में इसे कैसे पूरा करते हैं?

जवाबों:


21

नेविगेशन को हमेशा ViewModel में संभाला जाना चाहिए।

आप यह सोचकर सही रास्ते पर हैं कि एमवीवीएम डिज़ाइन पैटर्न का सही क्रियान्वयन का मतलब है कि आप अपने आवेदन को पूरी तरह से बिना दृश्यों के चला सकते हैं, और आप ऐसा नहीं कर सकते हैं यदि आपका दृश्य आपके नेविगेशन को नियंत्रित करता है।

मेरे पास आमतौर पर एक ApplicationViewModel, या ShellViewModel, जो मेरे आवेदन की समग्र स्थिति को संभालता है। इसमें CurrentPage(जो एक ViewModel है) और हैंडलिंग के लिए कोड शामिल है ChangePageEvents। (इसका उपयोग अक्सर अन्य एप्लिकेशन-वाइड ऑब्जेक्ट्स के लिए भी किया जाता है जैसे कि CurrentUser, या ErrorMessages भी)

इसलिए यदि कोई भी ViewModel, कहीं भी प्रसारण करता है ChangePageEvent(new SomePageViewModel), तो ShellViewModelउस संदेश को पिक करेगा और संदेश में CurrentPageजो भी पृष्ठ निर्दिष्ट किया गया था, उस पर स्विच करेगा ।

यदि आप रुचि रखते हैं तो मैंने वास्तव में MVVM के साथ नेविगेशन के बारे में एक ब्लॉग पोस्ट लिखा है


2
दिलचस्प दृष्टिकोण। चार टिप्पणियाँ: 1) Silverlight DataTemplate पर DataType संपत्ति का समर्थन नहीं करता है इसलिए ViewModel में DataTemplate की मैपिंग SL में संभव नहीं है। 2) यह दृश्य और ViewModels के बीच कई-से-कई संभावनाओं को संबोधित नहीं करता है। 3) यह चाइल्ड विंडो को हैंडल नहीं करता (या कम से कम मैं नहीं देखता कि कैसे)। 4) आपके एप्लिकेशन / शेल व्यूमॉडल के बीच चुस्त-युग्मन की आवश्यकता है और यह बच्चे (पोते, आदि) हैं। अगर मेरे ऐप में 40 पृष्ठ हैं, तो यह व्यूमॉडल प्रबंधन के लिए बोझिल होगा।
सोनऑफपिरेट

उस ने कहा, यह निश्चित रूप से विचार करने के लिए कुछ है।
सोनऑफपिरेट

@SonOfPirate 1) Silverlight निहित डेटाटेम्पलेट मैपिंग (अभी तक) का समर्थन नहीं करता है, हालाँकि यह एक समर्थन करता है DataTemplateSelector, जो कि मैं आमतौर पर Silverlight ऐप्स के लिए उपयोग करता हूं। 2) मैंने पहले भी कई-से-कई स्थितियों में इसका उपयोग किया है। उदाहरण के लिए, एक ViewModel में कई दृश्य हो सकते हैं, या एक View कई ViewModels से संबद्ध हो सकते हैं। पूर्व के एक उदाहरण के लिए, rachel53461.wordpress.com/2011/05/28/… देखें । बाद के लिए, आपको अपने डेटाटैम्प्लीसेंटर में एक ही दृश्य में कई ViewModels मानचित्र निर्दिष्ट करने की आवश्यकता है।
राहेल

3) यह सिर्फ एक मूल उदाहरण है। यदि आप जानते हैं कि आपका एप्लिकेशन कई विंडोज़ होने जा रहा है, तो आप स्पष्ट रूप से कई को संभालने के लिए ShellViewModel को बदल देंगे CurrentPages) एक बार फिर, यह सिर्फ एक मूल उदाहरण था। वास्तव में, मेरा PageViewModels सभी कुछ आधार वर्ग पर आधारित है, इसलिए मेरा ShellViewModel केवल आधार वर्ग या इंटरफ़ेस के साथ काम करता है, जैसे IPageViewModel। वास्तव में मैपिंग का सबसे बड़ा गन्दा टुकड़ा DataTemplateSelector है, जिसे 40 दृश्य से 40 ViewModels पर मैप करना होगा।
राहेल

@SonOfPirate मुझे उम्मीद है कि आपके कुछ सवालों के जवाब दिए। बेझिझक मुझे चैट में देखने के लिए स्वतंत्र हैं अगर आपके पास दूसरों :)
राहेल

6

बंद करने के लिए, मैंने सोचा था कि मैं इस समस्या को हल करने के लिए आखिरकार दिशा को चुनूंगा।

पहला निर्णय सिल्वरलाइट पेज नेविगेशन ढांचे का लाभ उठाना था, जो आउट-ऑफ-द-बॉक्स प्रदान करता था। यह निर्णय ज्ञान सहित कई कारकों पर आधारित था कि इस प्रकार के नेविगेशन को माइक्रोसॉफ्ट द्वारा विंडोज 8 मेट्रो ऐप में आगे बढ़ाया जा रहा है और यह फोन 7 ऐप में नेविगेशन के अनुरूप है।

इसे काम करने के लिए, मैंने अगला काम ASP.NET MVC के कन्वेंशन-बेस्ड नेविगेशन के साथ किया है। फ़्रेम नियंत्रण प्रदर्शन करने के लिए 'पृष्ठ' का पता लगाने के लिए यूआरआई का उपयोग करता है। समानता ने सिल्वरलाइट ऐप में समान सम्मेलन-आधारित दृष्टिकोण का उपयोग करने का अवसर प्रदान किया। चाल यह सब एक MVVM तरीके से एक साथ काम कर रहा था।

इसका समाधान नेवीगेशन सर्विस है। यह सेवा कई तरीकों को उजागर करती है, जैसे कि NavigateTo और Back, जिसे ViewModels पृष्ठ परिवर्तन शुरू करने के लिए उपयोग कर सकता है। जब कोई नया पृष्ठ अनुरोध किया जाता है, तो नेविगेशनवी सर्विस एमवीवीएमएलटी मैसेंजर सुविधा का उपयोग करके करंटपेजेजमेज़ेज भेजता है।

फ़्रेम नियंत्रण वाले दृश्य का अपना स्वयं का ViewModel DataContext है जो इस संदेश के लिए सुन रहा है। जब प्राप्त होता है, तो नए दृश्य का नाम एक मैपिंग फ़ंक्शन के माध्यम से रखा जाता है जो हमारे कन्वेंशन नियमों को लागू करता है और CurrentPage संपत्ति पर सेट होता है। फ़्रेम नियंत्रण का स्रोत गुण CurrentPage गुण के लिए बाध्य है। नतीजतन, संपत्ति सेट करना स्रोत को अपडेट करता है और नेविगेशन को ट्रिगर करता है।

नेवीगेशन सर्विस पर वापस जाना। NavigateTo विधि लक्ष्य पृष्ठ के नाम को स्वीकार करती है। यह सुनिश्चित करने के लिए कि ViewModels में कोई UI चिंता नहीं है, उपयोग किया जाने वाला नाम ViewModel प्रदर्शित करने का नाम है। मैंने वास्तव में एक संस्मरण बनाया है जिसमें प्रत्येक नौगम्य ViewModel के लिए एक सहायक के रूप में एक क्षेत्र है और पूरे ऐप में जादू के तार को खत्म करने के लिए है। मेरे द्वारा उल्लिखित मानचित्रण समारोह नाम से "ViewModel" प्रत्यय को छीन लेगा, नाम में "पृष्ठ" जोड़ देगा और पूरा नाम "दृश्य {नाम} Page.xaml" सेट कर देगा।

इसलिए, उदाहरण के लिए, ग्राहक विवरण देखने के लिए नेविगेट करने के लिए, मैं कॉल कर सकता हूं:

NavigationService.NavigateTo(ViewModels.CustomerDetails);

CustomerDetails का मान "CustomerDetailsViewModel" है जिसे "Views \ CustomerDetailsPage.xaml" पर मैप किया जाता है।

इस दृष्टिकोण की सुंदरता यह है कि UI पूरी तरह से ViewModels से डिकोड हो गया है फिर भी हमारे पास पूर्ण नेविगेशन समर्थन है। मैं अब अपने आवेदन को फिर से जमा कर सकता हूं और जब भी मैं किसी भी कोड परिवर्तन के बिना फिट देखूंगा।

आशा है कि व्याख्या मदद करती है।


2

राहेल ने जो कहा, उसके समान, मेरे ज्यादातर-एमवीवीएम एप्लिकेशन में Presenterखिड़कियों या पृष्ठों के बीच स्विच को संभालने के लिए है। राहेल इसे एक कॉल करता है ApplicationViewModel, लेकिन मेरे अनुभव में, इसे आम तौर पर एक बाध्यकारी लक्ष्य से अधिक करना पड़ता है (जैसे संदेश प्राप्त करना, विंडोज बनाना, आदि) इसलिए यह तकनीकी रूप से एक पारंपरिक Presenterया की तरह अधिक है Controller

मेरे आवेदन में, मेरी Presenterशुरुआत ए से होती है CurrentViewModelPresenterके बीच सभी संचार को बीच में रोक Viewऔर ViewModel। एक ViewModelबातचीत के दौरान कर सकने वाली चीजों में से एक नया है ViewModel, जिसका अर्थ है एक नया पृष्ठ या एक नया Windowप्रदर्शित किया जाना चाहिए। Presenterबनाने या अधिलेखित का ख्याल रखता है Viewनए के लिए ViewModelऔर स्थापित करने DataContext

एक क्रिया का परिणाम यह भी हो सकता है कि एक ViewModel"पूर्ण" है, जिस स्थिति में यह Presenterपता लगाता है और खिड़की को बंद कर देता है, या ViewModelइसे वीएम स्टैक से हटा देता है और पिछले पृष्ठ को प्रदर्शित करने के लिए वापस जाता है।


प्रस्तुतकर्ता को यह कैसे पता चलता है कि प्रदर्शन क्या है?
SonOfPirate 13:17 पर

1
@SonOfPirate - यह आम तौर पर WPF तंत्र के माध्यम से किया जाता है। Presenterसिर्फ लाठी लौटे ViewModelदृश्य पेड़ में, और WPF उचित पकड़ लेता है View, ऊपर हुक DataContextदृश्य पेड़ में बजाय कि, और कहते हैं। आप यह कर सकते हैं DataTemplateकि आप किस ViewModelप्रकार के रेंडर की घोषणा करते हैं या आप कस्टम डेटा टेम्प्लेट चयनकर्ता बना सकते हैं। यह अभी भी WPF सुविधाओं के दायरे में है।
स्कॉट व्हिटलॉक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.