विंडोज रूपों के लिए सबसे अच्छा डिज़ाइन जो सामान्य कार्यक्षमता साझा करेगा


20

अतीत में, मैंने अपने आवेदन में विंडोज रूपों के विस्तार की अनुमति देने के लिए विरासत का उपयोग किया है। यदि मेरे सभी रूपों में सामान्य नियंत्रण, कलाकृति, और कार्यक्षमता होगी, तो मैं सामान्य नियंत्रण और कार्यक्षमता को लागू करने वाला एक आधार प्रपत्र बनाऊंगा और फिर अन्य नियंत्रणों को उस आधार रूप से प्राप्त करने की अनुमति दूंगा। हालाँकि, मैं उस डिज़ाइन के साथ कुछ समस्याओं में चला गया हूँ।

  1. नियंत्रण केवल एक समय में एक कंटेनर में हो सकते हैं, इसलिए आपके पास कोई भी स्थैतिक नियंत्रण मुश्किल होगा। उदाहरण के लिए: मान लीजिए कि आपके पास बेस फॉर्म था जिसका नाम बेसफार्म था जिसमें ट्रीव्यू शामिल था जिसे आप संरक्षित और स्थिर बनाते हैं ताकि इस वर्ग के अन्य (व्युत्पन्न) सभी उदाहरण उसी ट्री व्यू को संशोधित और प्रदर्शित कर सकें। यह बेसफ़ॉर्म से विरासत में मिली कई कक्षाओं के लिए काम नहीं करेगा, क्योंकि ट्री व्यू केवल एक समय में एक कंटेनर में हो सकता है। यह संभवतः प्रारंभिक रूप से अंतिम रूप में होगा। हालांकि हर उदाहरण नियंत्रण को संपादित कर सकता है, यह केवल एक निश्चित समय में प्रदर्शित होगा। बेशक, काम के आसपास हैं, लेकिन वे सभी बदसूरत हैं। (यह मेरे लिए एक बहुत बुरा डिजाइन है। क्यों कई कंटेनर एक ही वस्तु के लिए संकेत स्टोर नहीं कर सकते हैं? किसी भी तरह, यह वही है जो यह है।)

  2. प्रपत्रों के बीच की स्थिति, यानी बटन स्टेट्स, लेबल टेक्स्ट आदि। मुझे लोड पर राज्यों को रीसेट करने और रीसेट करने के लिए वैश्विक चर का उपयोग करना होगा।

  3. यह वास्तव में विजुअल स्टूडियो के डिजाइनर द्वारा बहुत अच्छी तरह से समर्थित नहीं है।

वहाँ एक बेहतर, अभी भी आसानी से बनाए रखने योग्य डिजाइन का उपयोग करने के लिए है? या क्या फॉर्म इनहेरिटेंस अभी भी सबसे अच्छा तरीका है?

अपडेट मैं एमवीसी को एमवीपी से ऑब्जर्वर पैटर्न को इवेंट पैटर्न में देखने पर गया। यहाँ मैं इस समय के लिए सोच रहा हूँ, कृपया समालोचना करें:

मेरे बेसफ़ॉर्म वर्ग में केवल नियंत्रण होंगे, और उन नियंत्रणों से जुड़ी घटनाएं। उन सभी घटनाओं को जिन्हें संभालने के लिए किसी भी प्रकार के तर्क की आवश्यकता होती है, तुरंत बेसफ़ॉर्मप्रेज़ेंट क्लास में पास हो जाएगी। यह वर्ग UI से डेटा को संभालेगा, कोई तार्किक कार्य करेगा और फिर BaseFormModel को अपडेट करेगा। मॉडल उन घटनाओं को उजागर करेगा, जो राज्य परिवर्तन पर प्रस्तुतकर्ता वर्ग को आग देगा, जिसे वह सदस्यता देगा (या निरीक्षण करेगा)। जब प्रस्तुतकर्ता घटना सूचना प्राप्त करता है, तो यह कोई भी तर्क देगा, और फिर प्रस्तुतकर्ता तदनुसार दृश्य को संशोधित करेगा।

स्मृति में केवल प्रत्येक मॉडल वर्ग में से एक होगा, लेकिन संभवतः बेसफोर्म के कई उदाहरण हो सकते हैं और इसलिए बेसफार्मर। यह बेसफ़ॉर्म के प्रत्येक उदाहरण को एक ही डेटा मॉडल में सिंक्रनाइज़ करने की मेरी समस्या को हल करेगा।

प्रशन:

कौन सी परत को अंतिम दबाया गया बटन की तरह सामान संग्रहीत करना चाहिए, ताकि मैं इसे उपयोगकर्ता के लिए हाइलाइट रख सकूं (जैसे सीएसएस मेनू में) रूपों के बीच?

कृपया इस डिजाइन की आलोचना करें। आपकी सहायताके लिए धन्यवाद!


मैं नहीं देखता कि आपको वैश्विक चर का उपयोग करने के लिए क्यों मजबूर किया जाता है, लेकिन यदि हां तो निश्चित रूप से एक बेहतर दृष्टिकोण होना चाहिए। हो सकता है कि कारखानों में विरासत के बजाय रचना के साथ संयुक्त आम घटक बनाने हों?
१०

आपका पूरा डिज़ाइन त्रुटिपूर्ण है। यदि आप पहले से ही समझते हैं कि आप क्या करना चाहते हैं तो विजुअल स्टूडियो द्वारा समर्थित नहीं है जो आपको कुछ बताना चाहिए।
रामहुंड

1
@ रामहाउंड यह दृश्य स्टूडियो द्वारा समर्थित है, बस ठीक नहीं है। ऐसा Microsoft आपको करने के लिए कहता है। मुझे सिर्फ ए। Msdn.microsoft.com/en-us/library/aa983613(v=vs.71).aspx में किसी भी तरह का दर्द हो रहा है। यदि आपके पास बेहतर विचार है, तो मैं सभी आँखें हूँ।
जोनाथन हेंसन

@stijn मुझे लगता है कि मेरे पास प्रत्येक बेस फॉर्म में एक विधि हो सकती है जो नियंत्रण राज्यों को दूसरे उदाहरण में लोड करेगी। यानी LoadStatesToNewInstance (BaseForm उदाहरण)। मैं इसे कभी भी कॉल कर सकता हूं मैं उस आधार प्रकार का एक नया रूप दिखाना चाहता हूं। form_I_am_about_to_hide.LoadStatesToNewInstance (this);
जोनाथन हेंसन

मैं एक .net डेवलपर नहीं हूं, क्या आप बिंदु संख्या 1 पर विस्तार कर सकते हैं? मेरे पास एक समाधान हो सकता है
इमरान उमर बुकश

जवाबों:


6
  1. मुझे नहीं पता कि आपको स्थिर नियंत्रण की आवश्यकता क्यों है। हो सकता है कि आपको कुछ पता हो जो मैं नहीं करता। मैंने बहुत सारे दृश्य वंशानुक्रम का उपयोग किया है लेकिन मैंने आवश्यक होने के लिए स्थिर नियंत्रण कभी नहीं देखा है। यदि आपके पास एक सामान्य ट्रीव्यू नियंत्रण है, तो प्रत्येक प्रपत्र उदाहरण को नियंत्रण का अपना उदाहरण है, और ट्रीव्यू से जुड़े डेटा का एक भी उदाहरण साझा करें ।

  2. रूपों के बीच नियंत्रण स्थिति (डेटा के विपरीत) साझा करना भी एक असामान्य आवश्यकता है। क्या आप सुनिश्चित हैं कि फॉर्मबी को फॉर्म के बटन की स्थिति के बारे में जानना आवश्यक है? एमवीपी या एमवीसी डिजाइनों पर विचार करें। प्रत्येक रूप को एक गूंगा "दृश्य" के रूप में सोचें जो अन्य विचारों या यहां तक ​​कि आवेदन के बारे में कुछ भी नहीं जानता है। स्मार्ट प्रस्तोता / नियंत्रक के साथ प्रत्येक दृश्य का पर्यवेक्षण करें। यदि यह समझ में आता है, तो एक एकल प्रस्तुतकर्ता कई विचारों का पर्यवेक्षण कर सकता है। प्रत्येक दृष्टि से एक राज्य वस्तु को संबद्ध करें। यदि आपके पास कुछ राज्य हैं जिन्हें विचारों के बीच साझा करने की आवश्यकता है, तो प्रस्तुतकर्ता को इस पर ध्यान दें (और डेटाबाइंडिंग पर विचार करें - नीचे देखें)।

  3. सहमत, विजुअल स्टूडियो आपको सिरदर्द देगा। जब फॉर्म या यूजर कॉन्ट्रॉल इनहेरिटेंस पर विचार करते हैं, तो आपको फॉर्म डिजाइनर की निराशाजनक quirks और सीमाओं के साथ कुश्ती की संभावित (संभावित) लागत के खिलाफ लाभों को सावधानीपूर्वक तौलना होगा। मेरा सुझाव है कि फॉर्म इनहेरिटेंस को न्यूनतम रखने के लिए - इसका उपयोग केवल तभी करें जब भुगतान अधिक हो। ध्यान रखें कि, उपवर्ग के विकल्प के रूप में, आप सामान्य "आधार" फ़ॉर्म बना सकते हैं और बस एक बार "प्रत्येक" बच्चे के लिए इसे तुरंत लिख सकते हैं और फिर इसे मक्खी पर अनुकूलित कर सकते हैं। यह तब समझ में आता है जब साझा पहलुओं की तुलना में फॉर्म के प्रत्येक संस्करण के बीच अंतर मामूली होते हैं। (आईओडब्ल्यू: जटिल आधार रूप, केवल मामूली-अधिक-जटिल बाल रूप)

जब यूआई विकास के महत्वपूर्ण दोहराव को रोकने में आपकी मदद करता है, तो यूजर कॉंट्रोल का उपयोग करें। उपयोगकर्ताकंट्रोल इनहेरिटेंस पर विचार करें लेकिन फॉर्म इनहेरिटेंस के लिए समान विचार लागू करें।

मुझे लगता है कि सबसे महत्वपूर्ण सलाह जो मैं पेश कर सकता हूं, यदि आप वर्तमान में कुछ प्रकार के दृश्य / नियंत्रक पैटर्न को नियोजित नहीं करते हैं, तो मैं आपको इसे शुरू करने के लिए दृढ़ता से प्रोत्साहित करता हूं। यह आपको ढीला-कूपिंग और परत अलगाव के लाभों को सीखने और सराहना करने के लिए मजबूर करता है।

आपके अपडेट की प्रतिक्रिया

किस परत को सामान को स्टोर करना चाहिए, अंतिम दबाया गया बटन, ताकि मैं इसे उपयोगकर्ता के लिए हाइलाइट रख सकूं ...

आप राज्य को विचारों के बीच साझा कर सकते हैं जैसे आप एक प्रस्तुतकर्ता और उसके विचार के बीच राज्य साझा करेंगे। एक विशेष श्रेणी साझा करें साझा करें। सादगी के लिए आप इसे एक सिंगलटन बना सकते हैं, या आप इसे मुख्य प्रस्तुतकर्ता में इंस्टेंट कर सकते हैं और इसे वहां से (अपने प्रेजेंटर्स के माध्यम से) सभी दृश्यों को पास कर सकते हैं। जब राज्य नियंत्रण से जुड़ा होता है, तो जहां संभव हो डेटा बाइंडिंग का उपयोग करें। अधिकांश Controlगुण डेटा-बाउंड हो सकते हैं। उदाहरण के लिए एक बटन की BackColor संपत्ति आपके SharedViewState वर्ग की संपत्ति के लिए बाध्य हो सकती है। यदि आप उन सभी रूपों पर बाइंडिंग करते हैं जिनमें समान बटन हैं, तो आप बस सेटिंग करके सभी रूपों पर Button1 हाइलाइट कर सकते हैं SharedViewState.Button1BackColor = someColor

यदि आप WinForms डेटाबाइंडिंग से परिचित नहीं हैं, तो MSDN को हिट करें और कुछ पढ़ें। यह कठिन नहीं है। के बारे में जानें INotifyPropertyChangedऔर आप आधे रास्ते में हैं।

यहाँ एक उदाहरण के रूप में Button1BackColor संपत्ति के साथ एक विशिष्ट श्रेणी का कार्यान्वयन है:

public class SharedViewState : INotifyPropertyChanged
{
    // boilerplate INotifyPropertyChanged stuff
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    // example of a property for data-binding
    private Color button1BackColor;
    public Color Button1BackColor
    {
        get { return button1BackColor; }
        set
        {
            if (value != button1BackColor)
            {
                button1BackColor = value;
                NotifyPropertyChanged("Button1BackColor");
            }
        }
    }
}

आपके विचारपूर्ण उत्तर के लिए धन्यवाद। क्या आप व्यू / कंट्रोलर पैटर्न के अच्छे संदर्भ के बारे में जानते हैं?
जोनाथन हेंसन

1
मुझे याद है कि यह सोच काफी अच्छा परिचय था: codebetter.com/jeremymiller/2007/05/22/…
Igby Largeman

कृपया मेरा अपडेट देखें।
जोनाथन हेंसन

@ जोंथनथनसन: उत्तर अपडेट किया गया।
इग्बी लार्गेमैन

5

मैं MVVM पैटर्न और अपडेट नियंत्रण के आधार पर एक नया WinForms / WPF एप्लिकेशन बनाए रखता हूं । यह WinForms के रूप में शुरू हुआ, फिर मैंने एक UI के विपणन महत्व के कारण WPF संस्करण बनाया जो अच्छा दिखता है। मैंने सोचा था कि यह एक दिलचस्प डिज़ाइन बाधा होगी जो एक आवेदन को बनाए रखने के लिए एक ही बैकएंड कोड (viewmodels और मॉडल) के साथ दो पूरी तरह से अलग-अलग UI प्रौद्योगिकियों का समर्थन करती है, और मुझे कहना है कि मैं इस दृष्टिकोण से काफी संतुष्ट हूं।

मेरे ऐप में, जब भी मुझे UI के कुछ हिस्सों के बीच कार्यक्षमता साझा करने की आवश्यकता होती है, तो मैं कस्टम नियंत्रण या उपयोगकर्ता नियंत्रण (WPF UserControl या WinForms UserControl से प्राप्त कक्षाएं) का उपयोग करता हूं। WinForms संस्करण में TabPage के एक व्युत्पन्न वर्ग के अंदर एक अन्य UserControl के अंदर एक UserControl है, जो अंततः मुख्य रूप पर एक टैब नियंत्रण के अंदर है। WPF संस्करण में वास्तव में UserControls का एक स्तर गहरा है। कस्टम नियंत्रणों का उपयोग करते हुए, आप आसानी से UserControls से एक नया UI बना सकते हैं जिसे आपने पहले बनाया था।

चूंकि मैं MVVM पैटर्न का उपयोग करता हूं, इसलिए मैं ViewModel ( प्रस्तुति / नेविगेशन मॉडल सहित) में अधिक से अधिक कार्यक्रम तर्क देता हूं ) या मॉडल (कोड यूजर इंटरफेस से संबंधित है या नहीं) के आधार पर , लेकिन उसी व्यूकोड के बाद से एक WinForms दृश्य और एक WPF दृश्य दोनों द्वारा उपयोग किया जाता है, ViewModel को WinForms या WPF के लिए डिज़ाइन किया गया कोड शामिल करने की अनुमति नहीं है या जो सीधे UI के साथ इंटरैक्ट करता है; इस तरह के कोड को देखने में जाना चाहिए।

एमवीवीएम पैटर्न में भी, यूआई ऑब्जेक्ट्स को एक-दूसरे के साथ बातचीत करने से बचना चाहिए! इसके बजाय वे व्यूमोडल्स के साथ बातचीत करते हैं। उदाहरण के लिए, एक टेक्स्टबॉक्स पास के लिस्टबॉक्स से यह नहीं पूछेगा कि कौन सा आइटम चुना गया है; इसके बजाय सूची बॉक्स दृश्यदर्शी परत में कहीं न कहीं वर्तमान में चयनित आइटम के संदर्भ को बचाएगा, और टेक्स्टबॉक्स दृश्यमॉडल परत को यह पता लगाने के लिए क्वेरी करेगा कि अभी क्या चुना गया है। यह आपकी समस्या को हल करने के बारे में पता लगाता है कि किस बटन को एक अलग रूप में एक रूप में धकेल दिया गया था। आप बस दो रूपों के बीच एक नेविगेशन मॉडल ऑब्जेक्ट (जो एप्लिकेशन के व्यूमोडेल लेयर का हिस्सा है) को साझा करते हैं और उस ऑब्जेक्ट में एक संपत्ति डालते हैं जो यह दर्शाता है कि किस बटन को धक्का दिया गया था।

WinForms स्वयं MVVM पैटर्न का अच्छी तरह से समर्थन नहीं करते हैं, लेकिन Update Controls अपने स्वयं के अनूठे दृष्टिकोण MVVM को एक लाइब्रेरी के रूप में प्रदान करता है जो WinForms के शीर्ष पर बैठता है।

मेरी राय में, प्रोग्राम डिज़ाइन के लिए यह दृष्टिकोण बहुत अच्छा काम करता है और मैं इसे भविष्य की परियोजनाओं पर उपयोग करने की योजना बना रहा हूं। जिन कारणों से यह इतनी अच्छी तरह से काम करता है वे हैं (1) जो कि अपडेट नियंत्रण स्वचालित रूप से निर्भरता का प्रबंधन करता है, और (2) यह आमतौर पर बहुत स्पष्ट है कि आपको अपना कोड कैसे बनाना चाहिए: UI कोड के साथ इंटरैक्ट करने वाला सभी कोड व्यू में है, जो सभी कोड है UI- संबंधित लेकिन UI ऑब्जेक्ट के साथ सहभागिता करने के लिए ViewModel में नहीं है। अक्सर आप अपने कोड को दो भागों में विभाजित करेंगे, एक भाग व्यू के लिए और दूसरा भाग व्यूमॉडल के लिए। मुझे अपने सिस्टम में संदर्भ मेनू डिजाइन करने में कुछ कठिनाई हुई, लेकिन आखिरकार मैं इसके लिए एक डिजाइन भी लेकर आया।

मैंने अपने ब्लॉग पर अपडेट नियंत्रण के बारे में भी जानकारी दी है। इस दृष्टिकोण का उपयोग करने में बहुत अधिक समय लगता है, हालांकि, और बड़े पैमाने पर ऐप्स में (जैसे कि यदि आपके लिस्टबॉक्स में हजारों आइटम हैं) तो आप स्वचालित निर्भरता प्रबंधन की वर्तमान सीमाओं के कारण प्रदर्शन समस्याओं का सामना कर सकते हैं।


3

मैं इसका उत्तर देने जा रहा हूं, भले ही आपने पहले ही उत्तर स्वीकार कर लिया हो।

जैसा कि दूसरों ने बताया है, मुझे समझ में नहीं आता है कि आपको कुछ भी स्थैतिक का उपयोग क्यों करना पड़ा; ऐसा लगता है कि आप बहुत गलत तरीके से कुछ कर रहे हैं।

वैसे भी, मुझे आपके समान ही समस्या है: मेरे WinForms आवेदन में मेरे पास कई रूप हैं जो कुछ कार्यक्षमता और कुछ नियंत्रण साझा करते हैं। इसके अलावा, मेरे सभी फॉर्म पहले से ही बेस फॉर्म से प्राप्त होते हैं (इसे "MyForm" कहते हैं), जो फ्रेम-लेवल फंक्शनलिटी (एप्लिकेशन की परवाह किए बिना) जोड़ता है। विज़ुअल स्टूडियो का फॉर्म डिज़ाइनर एडिटिंग फॉर्म का समर्थन करता है जो अन्य रूपों से इनहेरिट करता है, लेकिन जब तक आपके रूप "हैलो, दुनिया! - ठीक है - रद्द करें" से अधिक कुछ नहीं करते तब तक यह अभ्यास करता है।

मैंने जो किया है वह यह है: मैं अपने सामान्य आधार वर्ग "MyForm" को रखता हूं, जो काफी जटिल है, और मैं अपने सभी एप्लिकेशन के फॉर्म इससे प्राप्त करना जारी रखता हूं। हालांकि, मैं इन रूपों में कुछ भी नहीं करता हूं, इसलिए वीएस फॉर्म डिजाइनर को उन्हें संपादित करने में कोई समस्या नहीं है। ये फॉर्म पूरी तरह से कोड के होते हैं जो फॉर्म डिजाइनर उनके लिए बनाता है। फिर, मेरे पास वस्तुओं का एक अलग समानांतर पदानुक्रम है जिसे मैं "सरोगेट्स" कहता हूं, जिसमें सभी एप्लिकेशन-विशिष्ट कार्यक्षमता शामिल हैं, जैसे नियंत्रण को इनिशियलाइज़ करना, फॉर्म और नियंत्रण द्वारा उत्पन्न घटनाओं को संभालना, आदि एक-से-एक है। मेरे आवेदन में सरोगेट कक्षाओं और संवादों के बीच पत्राचार: एक आधार सरोगेट वर्ग है जो "MyForm" से मेल खाता है, फिर एक अन्य सरोगेट वर्ग प्राप्त होता है जो "MyApplicationForm" से मेल खाता है,

प्रत्येक सरोगेट एक निर्माण-समय पैरामीटर को एक विशिष्ट प्रकार के रूप में स्वीकार करता है, और यह अपने ईवेंट के लिए पंजीकरण करके इसे खुद को संलग्न करता है। यह आधार को "MySurrogate" के लिए सभी तरह से प्रस्तुत करता है, जो "MyForm" को स्वीकार करता है। वह सरोगेट फॉर्म के "डिसपोज्ड" इवेंट के साथ रजिस्टर करता है, ताकि जब फॉर्म नष्ट हो जाए, तो सरोगेट खुद पर एक ओवररिडबल आमंत्रित करता है, ताकि यह और उसके सभी वंशज, क्लीनअप कर सकें। (घटनाओं से डेरेगीस्टर, आदि)

यह अब तक ठीक काम कर रहा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.