2010-05-14 8 views
6

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

मुझे लगता है कि एक गैर-मोडल, हमेशा-शीर्ष-शीर्ष संवाद बनाने और उन अनुप्रयोग सुविधाओं को प्रोग्रामेटिक रूप से अक्षम करने का तरीका है जो संवाद पर लागू नहीं हैं। क्या WPF में इसे हासिल करने का कोई आसान तरीका है? या शायद एक डिजाइन पैटर्न है जिसे मैं अपना सकता हूं।

+0

मुझे लगता है कि आप सही रास्ते पर हैं। जब आप खिड़की खोले/बंद होते हैं, तो आप कोड-बैक में नियंत्रण को सक्षम/सक्षम कर सकते हैं, या आप अपने एक्सएएमएल में डेटाट्रिगर्स का उपयोग कर सकते हैं, नई विंडो खुली है या नहीं, इस पर आधारित विभिन्न नियंत्रणों के लिए 'IsEnabled' प्रॉपर्टी सेट कर सकते हैं। –

उत्तर

0

जो आप खोज रहे हैं वह Multiple Document Interface जैसा है। यह डिफ़ॉल्ट रूप से WPF में उपलब्ध नहीं है लेकिन इसका समर्थन करने के लिए वहां कुछ प्रयास हैं, free और commercial दोनों।

यह आपके लिए आवेदन की वर्तमान स्थिति की पहचान करने और इसके जवाब में यूआई तत्वों को सक्षम/अक्षम करने के लिए आप पर निर्भर करेगा।

+0

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

0

मुझे लगता है कि हमेशा एक शीर्ष-ऑन-टॉप विंडो जो कुछ ऐप सुविधाओं को प्रोग्रामेटिक रूप से अक्षम करती है, ऐसा करने का तरीका है। इस फॉर्म को खोलने के दौरान सुविधाओं की "श्वेत सूची" को रखना आसान हो सकता है, और इस सूची में मौजूद सभी चीज़ों को अक्षम कर सकते हैं (जैसा कि की सभी "ब्लैक लिस्ट" को बनाए रखने की कोशिश करने के विरोध में सक्षम नहीं हो सकता है)।

2

हां, पारंपरिक दृष्टिकोण है जहां आप वर्णन करते हैं कि आप प्रोग्रामेटिक रूप से सुविधाओं को सक्षम/अक्षम करते हैं, लेकिन डब्ल्यूपीएफ कई नई संभावनाएं भी खोलता है जो WinForms और पुरानी तकनीकों में वास्तव में संभव नहीं थे।

मैं यह करने के चार WPF-विशिष्ट तरीके की व्याख्या करेगा:

  • आप गुप्त रूप से और स्वचालित रूप से इसकी सामग्री, एक VisualBrush के साथ एक आयत का उपयोग करने का जिससे प्रभावी रूप से अक्षम करने के लिए एक तस्वीर के साथ एक खिड़की की सामग्री की जगह ले सकता यह। उपयोगकर्ता को यह दिखाई देगा कि खिड़की अपरिवर्तित है, लेकिन वास्तविक सामग्री तस्वीर के नीचे होगी, इसलिए आप इसे हिट-टेस्टिंग के लिए उपयोग कर सकते हैं और यहां तक ​​कि चयनित ईवेंट भी अग्रेषित कर सकते हैं।

  • आप अपनी विंडो के संसाधन डिक्शनरी में एक मर्ज किए गए डिक्शनरी को जोड़ सकते हैं जो सभी टेक्स्टबॉक्स को टेक्स्टब्लॉक बनने का कारण बनता है, सभी बटन अक्षम हो जाते हैं, आदि, कस्टम संलग्न गुणों का उपयोग करके स्पष्ट रूप से ओवरराइड किए जाने के अलावा। तो अपने सभी यूआई के माध्यम से चुनिंदा सक्षम/अक्षम करने के बजाय, आप बस मर्ज किए गए शब्दकोश संग्रह से किसी ऑब्जेक्ट को जोड़ या निकाल दें।

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

  • उपयोग बाध्यकारी डेटा और शैलियों सक्रिय/बल्कि खिड़की

    की तस्वीर के साथ खिड़की की जगह इस समाधान के लिए पर उन के माध्यम से पुनरावृत्ति

विवरण से अलग-अलग नियंत्रण को अक्षम, अपने अनुप्रयोग पुनरावृति खिड़कियां और प्रत्येक सामग्री को मूल सामग्री और एक आयत युक्त ग्रिड के साथ प्रतिस्थापित करें, जैसे:

<Window ...> 
    <Grid> 
    <ContentPresenter x:Name="OriginalContent" /> 
    <Rectangle> 
     <Rectangle.Fill> 
     <VisualBrush Visual="{Binding ElementName=OriginalContent}" /> 
     </Rectangle.Fill> 
    </Rectangle> 
    </Grid> 
</Window> 

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

<Window ...> 
    <my:SelectiveDisabler> 
    <Grid x:Name="LayoutRoot"> ... </Grid> <!-- Original content --> 
    </my:SelectiveDisabler> 
</Window> 

आयत करने के लिए माउस ईवेंट हैंडलर्स जोड़ने और निर्धारित करने के लिए क्या वस्तु मूल सामग्री में क्लिक किया गया था ContentPresenter पर VisualTreeHelper.HitTest बुला करके। इस बिंदु से आप माउस ईवेंट को अनदेखा करना चुन सकते हैं, इसे प्रसंस्करण के लिए मूल सामग्री पर अग्रेषित कर सकते हैं, या आंखों की नली नियंत्रण या ऑब्जेक्ट चयन सुविधा के मामले में, वांछित वस्तुओं/जानकारी को निकालें।

MergedDictionary दृष्टिकोण

पर विवरण जाहिर है आप अपने पूरे एक ResourceDictionary का उपयोग कर यूआई अपने खिड़की के संसाधनों में विलय कर दिया restyle कर सकते हैं।

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

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

यह विधि किसी अन्य संलग्न संपत्ति "IgnoreModalMode" को जोड़कर अपने यूआई के हिस्सों को चुनिंदा रूप से सक्षम/अक्षम करने का एक सुविधाजनक तरीका प्रदान करती है। आप मैन्युअल रूप से किसी भी UIElements पर इसे सही पर सेट कर सकते हैं जिसे आप नहीं चाहते हैं कि ModalMode पर लागू हो। आपका ModalMode PropertyChangedCallback तब यह जांचता है और यदि सत्य है, तो यह कुछ भी नहीं करता है।

InputManager दृष्टिकोण पर विवरण

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

<Setter Property="IsEnabled" Value="{Binding NonModal, Source={x:Static local:ModalModeTracker.Instance}}" /> 

:

बाध्यकारी

डेटा का उपयोग कर पर विवरण आप इस प्रकार का स्थिर मूल्य के लिए बटन, MenuItems, आदि के IsEnabled संपत्ति बाध्य करने के लिए एक शैलियों का उपयोग कर सकते हैं जब आपकी गैर-वाणिज्यिक संपत्ति झूठी हो जाती है तो इन शैलियों को स्वचालित रूप से अक्षम कर दिया जाएगा। हालांकि आपके मोडल मोड में भी सक्षम रहने के लिए कोई भी व्यक्तिगत नियंत्रण IsEnabled="true" के साथ ओवरराइड कर सकता है। मल्टीबाइंडिंग और ईडीएफ अभिव्यक्ति के साथ अधिक जटिल बाइंडिंग किए जा सकते हैं जो भी आप चाहते हैं नियम निर्धारित करने के लिए बाध्यकारी।


इनमें से कोई भी दृष्टिकोण आपके दृश्य इंटरफ़ेस के माध्यम से पुनरावृत्ति की आवश्यकता नहीं है, कार्यक्षमता को सक्षम और अक्षम करता है। इनमें से कौन सा आप वास्तव में चुनते हैं वह यह है कि आप वास्तव में मोडल मोड के दौरान कौन सी कार्यक्षमता प्रदान करना चाहते हैं, और आपका शेष यूआई कैसे डिज़ाइन किया गया है।

किसी भी मामले में, डब्ल्यूपीएफ WinForms दिनों में यह इतना आसान बनाता है। क्या आपको सिर्फ डब्ल्यूपीएफ की शक्ति पसंद नहीं है?

0

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

http://msdn.microsoft.com/en-us/library/ms752308.aspx

संबंधित मुद्दे

 संबंधित मुद्दे