2010-05-12 8 views
21

विंडोज़ फॉर्म एप्लिकेशन में, एक संपत्ति परिवर्तन जो INotifyPropertyChanged को ट्रिगर करता है, परिणामस्वरूप मेरे बाध्य ऑब्जेक्ट से प्रत्येक संपत्ति को पढ़ने का फॉर्म होगा, न केवल संपत्ति बदल दी जाएगी। (नीचे उदाहरण कोड देखें).NET WinForms InotifyProperty चेंज किए गए सभी बाइंडिंग अपडेट करते हैं जब कोई बदल जाता है। बेहतर तरीका?

यह बेहद अपर्याप्त लगता है क्योंकि इंटरफ़ेस को बदलती संपत्ति का नाम चाहिए। यह मेरे ऐप में बहुत सी घड़ी का कारण बन रहा है क्योंकि कुछ संपत्ति प्राप्तकर्ताओं को गणना करने की आवश्यकता होती है।

यदि मुझे ऐसा करने का कोई बेहतर तरीका नहीं है तो मुझे अनावश्यक पढ़ने को त्यागने के लिए मेरे गेटर्स में कुछ प्रकार के तर्क लागू करने की आवश्यकता होगी।

क्या मुझे कुछ याद आ रही है? क्या कोई बेहतर तरीका है? कृपया एक अलग प्रस्तुति तकनीक का उपयोग करने के लिए मत कहें - मैं इसे विंडोज मोबाइल पर कर रहा हूं (हालांकि व्यवहार पूरी ढांचे पर भी होता है)।

समस्या का प्रदर्शन करने के लिए यहां कुछ खिलौना कोड है। बटन पर क्लिक करने से दोनों संपत्तियों में बदलाव होने के बावजूद दोनों टेक्स्टबॉक्स पॉप्युलेट हो जाएंगे।

using System; 
using System.ComponentModel; 
using System.Drawing; 
using System.Windows.Forms; 

namespace Example 
{ 
public class ExView : Form 
{ 
    private Presenter _presenter = new Presenter(); 
    public ExView() 
    { 
     this.MinimizeBox = false; 

     TextBox txt1 = new TextBox(); 
     txt1.Parent = this; 
     txt1.Location = new Point(1, 1); 
     txt1.Width = this.ClientSize.Width - 10; 
     txt1.DataBindings.Add("Text", _presenter, "SomeText1"); 

     TextBox txt2 = new TextBox(); 
     txt2.Parent = this; 
     txt2.Location = new Point(1, 40); 
     txt2.Width = this.ClientSize.Width - 10; 
     txt2.DataBindings.Add("Text", _presenter, "SomeText2"); 

     Button but = new Button(); 
     but.Parent = this; 
     but.Location = new Point(1, 80); 
     but.Click +=new EventHandler(but_Click); 
    } 

    void but_Click(object sender, EventArgs e) 
    { 
     _presenter.SomeText1 = "some text 1"; 
    } 
} 

public class Presenter : INotifyPropertyChanged 
{ 

    public event PropertyChangedEventHandler PropertyChanged; 

    private string _SomeText1 = string.Empty; 
    public string SomeText1 
    { 
     get 
     { 
      return _SomeText1; 
     } 
     set 
     { 
      _SomeText1 = value; 
      _SomeText2 = value; // <-- To demonstrate that both properties are read 
      OnPropertyChanged("SomeText1"); 
     } 
    } 

    private string _SomeText2 = string.Empty; 
    public string SomeText2 
    { 
     get 
     { 
      return _SomeText2; 
     } 
     set 
     { 
      _SomeText2 = value; 
      OnPropertyChanged("SomeText2"); 
     } 
    } 

    private void OnPropertyChanged(string PropertyName) 
    { 
     PropertyChangedEventHandler temp = PropertyChanged; 
     if (temp != null) 
     { 
      temp(this, new PropertyChangedEventArgs(PropertyName)); 
     } 
    } 
} 

}

उत्तर

12

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

इस लेख को भी देखें, और विशेष रूप से यह टिप्पणी (http://www.codeproject.com/Messages/2514032/How-Binding-watches-control-properties-i-e-how-doe.aspx), जो बताती है कि संपत्ति का आयोजन कैसे किया जाता है, हालांकि यह आपके गेटर समस्या को संबोधित नहीं करेगा: http://www.codeproject.com/KB/database/databinding_tutorial.aspx?msg=2514032

पता लगाने का एक विचार है कि गेटर को बुलाया जा रहा है। आप बाइंडिंग की ControlUpdateMode प्रॉपर्टी के साथ खेलकर इसे प्राप्त कर सकते हैं। जब यह मान कभी भी सेट नहीं होता है, तो कोई परिवर्तन होने पर संबंधित नियंत्रण अपडेट नहीं होगा। हालांकि, जब आप मान को वापस OnPropertyChanged पर स्विच करते हैं, तो पुशडाटा विधि को कॉल किया जाएगा, इसलिए गेटर्स का उपयोग किया जाएगा। तो यह कोड अपने उदाहरण पर विचार अस्थायी पाठ बॉक्स 2 अद्यतन करने के लिए नहीं कर पाएगा:

void but_Click(object sender, EventArgs e) 
     {     
      txt2.DataBindings[0].ControlUpdateMode = ControlUpdateMode.Never; 
      _presenter.SomeText1 = "some text 1"; 
     } 
+0

मैं आपके द्वारा जो कुछ भी कहा है उससे सहमत हूं, मैंने आपके द्वारा उल्लिखित कोड को प्रतिबिंबित किया है। मैं आपकी प्रतिक्रिया को उत्तर के रूप में चिह्नित करने जा रहा हूं क्योंकि यह बहुत गहन है और आप मान्यता के लायक हैं, हालांकि, यह अच्छा होगा अगर कोई और जो इसे देखता है तो अतिरिक्त विकल्प प्रदान कर सकता है। बीटीडब्लू, यहां सिस्टम.Windows.Forms.BindToObject में विधि है जो उस नामस्थान और सिस्टम के बीच की सीमा पर अधिसूचना संपत्ति की जानकारी को छोड़ देता है। कॉम्पोनेंट मॉडल। प्रतिभाशाली। निजी शून्य PropValueChanged (ऑब्जेक्ट प्रेषक, EventArgs ई) { this.bindingManager.OnCurrentChanged (EventArgs.Empty); } –

+0

@anchandra आप कहते हैं: "_ जब यह मान कभी भी सेट नहीं होता है, तो जब कोई परिवर्तन होता है तो संबंधित नियंत्रण अपडेट नहीं होगा"। बस clearfi: 'DataSourceUpdateMode' निर्धारक जब * नियंत्रण * डेटा स्रोत में मान को धक्का देता है। तो नियंत्रण अभी भी डेटास्रोत संपत्ति परिवर्तन के बाद अद्यतन होगा। –

1

मैं इस तरह बंधन और OnPropertyChanged प्रबंध उपवर्गीकरण परीक्षण कर रहा हूँ, शायद आप में मदद करता है।

public class apBinding : Binding 
{ 

     public apBinding(string propertyName, INotifyPropertyChanged dataSource, string dataMember) 
      : base(propertyName, dataSource, dataMember) 
     { 
      this.ControlUpdateMode = ControlUpdateMode.Never; 
      dataSource.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged); 
     } 

     private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) 
     { 

      if (e.PropertyName == this.BindingMemberInfo.BindingField) 
      { 
       this.ReadValue(); 
      } 
     } 
    } 

अब समस्या मैं लगता है कि है कि नियंत्रण से जुड़ा हुआ वस्तु के मूल्य को अधिलेखित कर देता है, तो मैं

public class apBinding : Binding 
{ 

     public apBinding(string propertyName, INotifyPropertyChanged dataSource, string dataMember) 
      : base(propertyName, dataSource, dataMember) 
     { 

      dataSource.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged); 
     } 

     private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) 
     { 
      this.ControlUpdateMode = ControlUpdateMode.Never; 
      if (e.PropertyName == this.BindingMemberInfo.BindingField) 
      { 
       this.ReadValue(); 
      } 
     } 
    } 

करने के लिए संशोधित तो पहली बार propertychanges मैं controlupdate को निष्क्रिय कहा जाता है। और नियंत्रण पहले रन पर सही ढंग से अपडेट किया गया है।