2011-12-30 16 views
7

से बाध्यकारी देरी निम्नलिखित ViewModel संपत्ति पर विचार करें:एक सूत्र

private string _slowProperty; 
public string SlowProperty 
{ 
    get { return _slowProperty; } 
    set 
    { 
     _slowProperty = value; 
     RaisePropertyChanged("SlowProperty"); 
    } 
} 

कौन सा है, तो जैसे एक पाठ बॉक्स के लिए बाध्य है:

<TextBox Text="{Binding SlowProperty}" /> 

अब, समस्या यहाँ है हर बार का मूल्य है कि SlowProperty में परिवर्तन होता है, और यह अक्सर ऐसा करता है, टेक्स्टबॉक्स जायेगा और इसका मूल्य प्राप्त करने का प्रयास करेगा, जो काफी धीमा है। मैं एसिंक बाध्यकारी का उपयोग कर स्थिति को कम कर सकता हूं, हालांकि, यह अभी भी सीपीयू चक्र को बर्बाद कर देगा।

<TextBlock Text="{z:DelayedSourceBinding SlowProperty}" /> 

जो एक निश्चित विलंब के बाद बाध्यकारी प्राप्त करने की कोशिश करेंगे:

इसके बजाय, मैं क्या करना चाहते हैं की तरह कुछ है। तो उदाहरण के लिए यदि SlowProperty एक पंक्ति में 5 बार बदल गया है, तो थोड़ी देर के भीतर, केवल अंतिम टेक्स्ट टेक्स्टबॉक्स में दिखाई देगा।

मैं following project कि ऐसा ही कुछ करता है पाया है, तो यह मेरे उदाहरण मैं यह इतना की तरह इस्तेमाल कर सकते हैं:

<TextBox Text="{z:DelayBinding Path=SearchText}" /> 

इसके साथ समस्या है, यह केवल अद्यतन करता है कि बाध्यकारी लक्ष्य के बाद है देरी। स्रोत पथ, हालांकि, मूल्यांकन किया जाता है और स्रोत के हर परिवर्तन पर इसका गेटटर निष्पादित किया जाता है। जो, SlowProperty के मामले में अभी भी सीपीयू चक्र बर्बाद कर देगा।

मैंने अपनी देरी बाध्यकारी कक्षा बनाने की कोशिश की है, लेकिन got stuck। क्या कोई अन्य बांधने वाला यंत्र है जो ऐसा कुछ कर सकता है? DelayBinding को ऐसा ही एक समाधान -

DeferredBinding:

पूर्णता के लिए, यहाँ 2 अन्य परियोजनाओं है कि इसी तरह कार्य करते हैं, फिर भी, कोई भी पता समस्या मैं का सामना कर रहा है। हालांकि, यह उपयोग करने के लिए थोड़ा और जटिल है।

DelayedBindingTextBox - लागू कस्टम टेक्स्टबॉक्स नियंत्रण का उपयोग करके बाध्यकारी में देरी हुई।

धन्यवाद!

उत्तर

3

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

या, एक क्लीनर कार्यान्वयन Throttle प्रतिक्रियाशील एक्सटेंशन ढांचे द्वारा प्रदान किए गए फ़ंक्शन का उपयोग कर सकता है।

+0

कॉलिन, उत्कृष्ट। सभी सीएस समस्याओं को संकेत की एक और परत जोड़कर हल किया जा सकता है! :) –

+0

आप शायद सही हैं, वास्तव में, यह एक समस्या है जिसे वीएम स्तर पर हल किया जाना चाहिए। हालांकि, मैं अभी भी जानना चाहता हूं कि कस्टम बाइंडिंग करना संभव है, जैसा कि मैंने वर्णन किया है। – VitalyB

1

मुझे लगता है कि आप वास्तव में क्या चाहते हैं, उस बिंदु में देरी हो रही है जब RaisePropertyChanged() कहा जाता है।
तो मैं इसे बाहर की कोशिश की, और यहाँ एक समाधान है:

XAML:

<StackPanel> 
    <TextBox Text="{Binding DelayedText, UpdateSourceTrigger=PropertyChanged}" /> 
    <TextBlock Text="{Binding DelayedText}" /> 
</StackPanel> 

सी #:

public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      this.DataContext = this; 
     } 

     private String m_DelayedText; 
     public String DelayedText 
     { 
      get 
      { 
       return m_DelayedText; 
      } 
      set 
      { 
       if (m_DelayedText != value) 
       { 
        String delayedText; 
        m_DelayedText = delayedText = value; 
        Task.Factory.StartNew(() => 
         { 
          Thread.Sleep(2000); 
          if (delayedText == m_DelayedText) 
          { 
           RaisePropertyChanged("DelayedText"); 
          } 
         }); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     private void RaisePropertyChanged(String _Prop) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(_Prop)); 
      } 
     } 
    } 

आप देख सकते हैं कि यह RaisePropertyChanged("DelayedText") पर एक ब्रेकपाइंट सेट करके काम करता है

मैं समझता हूं कि यह "बस" संपत्ति के लिए बहुत सारे कोड की तरह दिख सकता है।
लेकिन आप कोड स्निपेट का उपयोग कर सकते हैं, या Resharper और इसी तरह के रनटाइम पर बॉयलरप्लेट कोड इंजेक्ट कर सकते हैं।
और वैसे भी, आपको शायद इसकी आवश्यकता नहीं होगी।

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

एचटीएच,

बाब।

+0

दिलचस्प समाधान, धन्यवाद! यह परिणामस्वरूप कोड पर वास्तव में थोड़ा भारी है, लेकिन यह एक दिलचस्प पढ़ा गया था। – VitalyB

2

मुझे थोड़ी देर की आवश्यकता थी, जहां मुझे स्रोत और लक्ष्य दोनों में देरी करने में सक्षम होना आवश्यक था, इसलिए मैंने DelayBinding और DelayMultiBinding नामक दो मार्कअप एक्सटेंशन बनाए। स्रोत के लिए एक अद्यतन करने में देरी करने के लिए आप UpdateSourceDelay

<TextBox Text="{db:DelayBinding SlowProperty, 
           UpdateSourceDelay='00:00:01'}" /> 

DelayBinding के लिए स्रोत कोड और नमूना उपयोग निर्दिष्ट और DelayMultiBindingdownloaded here हो सकता है।
आप कार्यान्वयन विवरण में रुचि रखते हैं, तो आप बाहर अपने ब्लॉग पोस्ट को इसके बारे में यहाँ देख सकते हैं:
DelayBinding and DelayMultiBinding with Source and Target delay

1
ध्यान दें

, नेट 4.5 के रूप में, एक delay property ढांचा है, जो देता है में जोड़ा गया है आप मिलीसेकंड द्वारा बाध्यकारी देरी की मात्रा निर्धारित करते हैं। माइक्रोसॉफ्ट उदाहरण में, twoway मोड पर जोर दिया जाता है लेकिन बाध्यकारी देरी किसी बाध्यकारी मोड में काम करती है।

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

SelectedValue="{Binding SampleNumberSelect, Mode=OneWayToSource, Delay=33}" 

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

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