2011-02-10 18 views
10

का उपयोग करते समय कोड और प्रस्तुति का सही अलगाव मेरे डब्ल्यूपीएफ में किसी भी इंटरफ़ेस से संबंधित डेटा से अपने कक्षा तर्क को अलग करने का प्रयास करें और बाध्यकारी के लिए केवल पर्यवेक्षण चयन गुणों को ही प्रदान करें।डिस्पैचर

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

मैं इसे और अधिक स्वच्छ और अलग तरीके से कैसे कर सकता हूं, इसलिए प्रेषक कॉल को मेरी विधियों से दूर किया जा सकता है?

उत्तर

2

विकल्प 1

मुझे लगता है कि आप अपने कोड MVVM पद्धति का उपयोग कर, यदि आप इसे से परिचित नहीं हैं की एक बेहतर जुदाई ध्यान देना चाहिए, मैं अत्यधिक following video देखने के लिए सुझाव है कि के रूप में यह वास्तव में क्या बताते हैं आप देख रहे हैं।

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

विकल्प 2

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

+1

+1 क्योंकि आपने जेसन से एमवीवीएम पर अद्भुत वीडियो का संदर्भ दिया :)। मुझे लगता है कि मैं हर जवाब को ऊपर उठाऊंगा जिसमें इसका एक लिंक होगा। पर्याप्त तनाव नहीं कर सकता कि यह कितना अच्छा है। खैर, और आपका जवाब सही है। – Anvaka

0

मुझे डर है कि आप WPF

के अगले संस्करण this post से के लिए प्रतीक्षा करनी होगी हूँ:

कुछ डली हम WPF के अगले संस्करण में देखने की उम्मीद कर सकते हैं शामिल हैं:

  • नए सिल्वरलाइटहोस्ट तत्व के साथ सिल्वरलाइट सामग्री की होस्टिंग, एयरस्पेस समस्याओं के बिना (देशी विंडोज एचडब्ल्यूएनडी सामग्री पर डब्ल्यूपीएफ सामग्री को ओवरलैप करने में असमर्थता)
  • WebBrowser तरह की मेजबानी देशी hWnd आधारित सामग्री के साथ हवाई क्षेत्र का समग्र बेहतर प्रबंधन, HwndHost और WindowsFormsHost
  • संग्रह एक पृष्ठभूमि धागे पर बनाए जाते हैं के लिए बाध्यकारी और परिवर्तन सूचना को सक्षम करने से
  • बेहतर यूआई वर्चुअलाइजेशन के साथ एकीकरण
  • रिबन नियंत्रण
  • की एकता और अधिक
3

मैं एक चांदी की गोली नहीं है। लेकिन अगर आप निश्चित यूआई प्रतिनिधिमंडल की ज़िम्मेदारी लेने के लिए निश्चित हैं और तैयार हैं, तो आप हमेशा ObservableCollection से उत्तराधिकारी, विधियों को ओवरराइड कर सकते हैं और यूआई को सभी अनुरोध भेज सकते हैं।

लेकिन निम्नलिखित कोड मुझे डरावना बना देता है:

// somewhere in thread pool: 
for(int i = 0; i < 1000; i++) 
{ 
    _dispatcherAwareCollection.Add(i); 
} 

यह मासूम लगता है, लेकिन हुड यह धागा 1000 बार बुला ब्लॉक के तहत। विकल्प आपकी विशिष्ट BulkXXX() विधियां हो सकती हैं, जो सभी तत्व संसाधित होने तक अधिसूचना में देरी कर सकती हैं। यह समाधान या तो सही नहीं है, क्योंकि आप एक अमूर्त चाहते थे जो आपको निर्बाध रूप से संग्रहों को स्वैप कर दे, लेकिन BulkXXX() विधियां नए संग्रह के लिए बहुत विशिष्ट हैं।

+0

इस विकल्प के बारे में भूल गए :) +1 –

0

डिस्पैचर के बजाय SynchronizationContext का उपयोग करें। सिंक्रनाइज़ेशन कॉन्टेक्स्ट .NET में थ्रेड सिंक्रनाइज़ेशन के लिए सामान्य सुविधा है, इस बीच डिस्पैचर जानबूझकर WPF के लिए विकसित किया गया है।

1

अच्छी तरह से आप इसे AsyncObservableCollection लिख सकते हैं, अगर आप इसे थ्रेडसेफ लिखना चाहते हैं। फिर आप इसमें कॉल को समाहित कर सकते हैं। समस्या यह है कि आप मानक ObservableCollection .Net - Framework के भीतर वितरित नहीं करेंगे। इससे आपके आवेदन में त्रुटियों का खतरा बढ़ जाएगा।

एक और विकल्प एक रैपर क्लास को लागू करना होगा, जिसमें बाध्यकारी के लिए ObservableCollection शामिल है और संग्रह को संशोधित करने के तरीके हैं।


public class WrapperClass<T> 
{ 
    public ObservableCollection<T> Collection {get; set;} 

    public void Add(T item) 
    { 
     //do your dispatcher magic here 
    } 
    ... 
} 

संग्रह को संशोधित करने के लिए आप इसमें विधियों को लागू करते हैं। यहां समस्या यह है कि कोई गारंटी नहीं है कि अन्य इन तरीकों का भी उपयोग करेंगे।

2

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

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

public class AsyncHelper 
{ 
    public static void EnsureUIThread(Action action) 
    { 
     if (Application.Current != null && !Application.Current.Dispatcher.CheckAccess()) 
     { 
      Application.Current.Dispatcher.BeginInvoke(action, DispatcherPriority.Background); 
     } 
     else 
     { 
      action(); 
     } 
    } 
} 

और जब भी आप आप नमूदार संग्रह अद्यतन करने की जरूरत है, तो आप आपको लगता है कि सहायक विधि में कोड लपेट:

AsyncHelper.EnsureUIThread(() => 
{ 
    // Update you observable collections here 
}); 

या, आप आगे जा सकते हैं और घोषणात्मक रूप से निर्दिष्ट करने के लिए एओपी (उदाहरण के लिए PostSharp) का उपयोग करें (गुणों का उपयोग करके) कि यूआई थ्रेड में एक विधि को निष्पादित किया जाना चाहिए।

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

+0

वह-वह, मुझे याद नहीं है कि मैंने कुछ ऐसा देखा जहां ... +1 – Anvaka

0

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

आलेख अच्छी तरह से पढ़ने योग्य है, भले ही आप इस विकल्प को लेने की योजना नहीं बनाते हैं।

0

मैं इस के लिए एक विस्तार है:

public static class DispatcherInvoker 
{  

    public static void AddOnUI<T>(this ICollection<T> collection, T item) 
    { 
     Action<T> addMethod = collection.Add; 
     Application.Current.Dispatcher.BeginInvoke(addMethod, item); 
    } 
} 

संपादित करें: मैं एक stackoverflow पद से यह चुरा लिया लेकिन भूल गया जहाँ से एक

0

मुझे लगता है कि आप बहुत युग्मन के लिए है, तो आप के बारे में सोचने की जरूरत अपने मॉडल परत में थ्रेडिंग।

आपको क्या करना चाहिए अपने मॉडल को सीधे जीयूआई से कनेक्ट नहीं करना है। जैसा कि अन्य ने कहा है, (एमवीवीएम) के बीच एक परत का उपयोग करें।

इसका मतलब है कि आप अपने एमवीवीएम परत को अपने अवलोकन संग्रह से परिवर्तन अधिसूचनाओं का जवाब देते हैं। यह एमवीवीएम परत है जो यह तय करती है कि जीयूआई पर इन अधिसूचनाओं को कब और कैसे पारित किया जाना चाहिए। इसे प्रयोग करने योग्य रखने के लिए जीयूआई की अद्यतन आवृत्ति को कम करने के तरीके के लिए here देखें।

संक्षेप में: यदि आप चाहें तो अपने मॉडल परत में एक ObeservableCollection का उपयोग करते रहें, लेकिन सीधे इसे GUI बाध्यकारी में उपयोग न करें। एक और परत अधिसूचनाएं प्राप्त करें और जीयूआई अद्यतन को नियंत्रित करें।

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