2011-10-06 9 views
15

है क्या कोई INOTifyPropertyChanged-like इंटरफ़ेस है जहां ईवेंट तर्क में संपत्ति का पुराना मान बदला जा रहा है, या क्या मुझे इसे बनाने के लिए उस इंटरफ़ेस को विस्तारित करना है?NotifyPropertyChanged ईवेंट जहां ईवेंट तर्क में पुराना मान

उदाहरण के लिए:

public String ProcessDescription 
    { 
     get { return _ProcessDescription; } 
     set 
     { 
      if(value != ProcessDescription) 
      { 
       String oldValue = _ProcessDescription; 
       _ProcessDescription = value; 
       InvokePropertyChanged("ProcessDescription", oldvalue); 
      } 
     } 
    } 

    InvokePropertyChanged(String PropertyName, OldValue) 
    { 
     this.PropertyChanged(new ExtendedPropertyChangedEventArgs(PropertyName, OldValue)); 
    } 

मैं भी एक PropertyChanging की तरह घटना है जो इस जानकारी प्रदान करता है, चाहे या नहीं यह e.Cancel का समर्थन करता है के लिए समझौता होगा।

उत्तर

30

जैसा कि उत्तरों से संकेत मिलता है, मुझे अपना स्वयं का समाधान लागू करना पड़ा। अन्य लोगों के लाभ के लिए, मैं इसे यहाँ प्रस्तुत किया है:

विस्तारित PropertyChanged घटना

इस घटना को विशेष रूप से पुराने PropertyChanged घटनाओं के साथ पीछे की ओर संगत होने के लिए किया गया है। इसका उपयोग कॉलर्स द्वारा सरल PropertyChangedEventArgs के साथ एक दूसरे के साथ किया जा सकता है। निस्संदेह, ऐसे मामलों में, यह जांचने के लिए ईवेंट हैंडलर की ज़िम्मेदारी है कि क्या संपत्ति का उपयोग किया गया है, अगर वे इसे इस्तेमाल करना चाहते हैं तो संपत्तिChangedEventArgs को संपत्तिChangedExtendedEventArgs में घटाया जा सकता है। यदि कोई दिलचस्पी नहीं है तो संपत्ति नाम संपत्ति है, तो कोई डाउनकास्टिंग आवश्यक नहीं है।

public class PropertyChangedExtendedEventArgs<T> : PropertyChangedEventArgs 
{ 
    public virtual T OldValue { get; private set; } 
    public virtual T NewValue { get; private set; } 

    public PropertyChangedExtendedEventArgs(string propertyName, T oldValue, T newValue) 
     : base(propertyName) 
    { 
     OldValue = oldValue; 
     NewValue = newValue; 
    } 
} 

विस्तारित PropertyChanged इंटरफ़ेस

, तो प्रोग्रामर ईवेंट बनाने के लिए है कि बलों सूचित गुण एक पुराने मूल्य और एक नया मान शामिल करना चाहता है, वे केवल निम्नलिखित इंटरफ़ेस को लागू करने की जरूरत :

// Summary: Notifies clients that a property value is changing, but includes extended event infomation 
/* The following NotifyPropertyChanged Interface is employed when you wish to enforce the inclusion of old and 
* new values. (Users must provide PropertyChangedExtendedEventArgs, PropertyChangedEventArgs are disallowed.) */ 
public interface INotifyPropertyChangedExtended<T> 
{ 
    event PropertyChangedExtendedEventHandler<T> PropertyChanged; 
} 

public delegate void PropertyChangedExtendedEventHandler<T>(object sender, PropertyChangedExtendedEventArgs<T> e); 

उदाहरण 1

उपयोगकर्ता अब एक और अधिक उन्नत NotifyPropertyChanged विधि संपत्ति setters अपने पुराने मूल्य में पारित करने के लिए अनुमति देता है कि निर्दिष्ट कर सकते हैं:

protected void NotifyPropertyChanged<T>(string propertyName, T oldvalue, T newvalue) 
{ 
    OnPropertyChanged(this, new PropertyChangedExtendedEventArgs<T>(propertyName, oldvalue, newvalue)); 
} 
:

public String testString 
{ 
    get { return testString; } 
    set 
    { 
     String temp = testString; 
     testValue2 = value; 
     NotifyPropertyChanged("TestString", temp, value); 
    } 
} 

कहाँ अपने नए NotifyPropertyChanged विधि इस तरह दिखता है

और OnPropertyChanged हमेशा जैसा ही है:

public virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    PropertyChangedEventHandler handler = PropertyChanged; 
    if (handler != null) 
     handler(sender, e); 
} 

उदाहरण 2

या हार्ड-कोडेड संपत्ति नाम तार के साथ भाग पूरी तरह से आप लैम्ब्डा एक्सप्रेशन का उपयोग करना पसंद करते हैं और अगर, आप निम्न का उपयोग कर सकते हैं:

public String TestString 
{ 
    get { return testString; } 
    private set { SetNotifyingProperty(() => TestString, ref testString, value); } 
} 

निम्नलिखित में से कौन जादू द्वारा समर्थित है :

protected void SetNotifyingProperty<T>(Expression<Func<T>> expression, ref T field, T value) 
{ 
    if (field == null || !field.Equals(value)) 
    { 
     T oldValue = field; 
     field = value; 
     OnPropertyChanged(this, new PropertyChangedExtendedEventArgs<T>(GetPropertyName(expression), oldValue, value)); 
    } 
} 
protected string GetPropertyName<T>(Expression<Func<T>> expression) 
{ 
    MemberExpression memberExpression = (MemberExpression)expression.Body; 
    return memberExpression.Member.Name; 
} 

प्रदर्शन

यदि प्रदर्शन एक चिंता है, तो यह प्रश्न देखें: Implementing NotifyPropertyChanged without magic strings

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

+0

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

+0

मैंने इस कोड का उपयोग करने की कोशिश की है और सामान्य 'INotifyPropertyChanged' के बजाय इंटरफ़ेस' INotifyPropertyChangedExtended 'को लागू करने के लिए ViewModel है, लेकिन मुझे दो तरह से बाध्यकारी नहीं मिला। – xavigonza

+2

मेरे लिए दो तरह से बाध्यकारी काम करता है। शायद कुछ ऐसा है जो आपको याद आया ... लेकिन ध्यान रखें कि आपको INotifyPropertyChangedExtended इंटरफ़ेस को लागू करने की आवश्यकता नहीं है। आपकी कक्षा में आप अभी भी INotifyPropertyChanged को कार्यान्वित कर सकते हैं, इसलिए आपकी कक्षा परिभाषा नहीं बदली है ... मुझे उस हिस्से को INotifyPropertyChangedExtended थोड़ा उलझन में मिला है। प्वाइंट है, उस इंटरफ़ेस को लागू न करें, केवल PropertyChangedExtendedEventArgs का उपयोग करें। – lightxx

1

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

+0

संपत्ति परिवर्तन अधिसूचनाओं की आवश्यकता है कि संपत्ति को इसके नाम से पहले अपना नया मूल्य सौंपा जाए। .Net Framework दस्तावेज़ देखें: http://msdn.microsoft.com/en-us/library/ms743695.aspx। मैं चाहता हूं कि अतिरिक्त जानकारी शामिल हो। – Alain

+0

आप सही हैं, मैं बस संपादन कर रहा था। –

3

लगता है जैसे आप INotifyPropertyChanged के साथ INotifyPropertyChanging का उपयोग करना चाहते हैं। एमएसडीएन दस्तावेज़ीकरण http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanging.aspx

+0

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

+0

1) एक ऑब्जेक्ट जो 'INotifyPropertyChanging' के लिए सुन रहा है, वह इस बात का प्रभारी क्यों नहीं होगा कि यह घटना के लिए क्यों सुन रहा है? एक अमूर्त दृष्टिकोण से मुझे लगता है कि किसी भी प्रोग्रामर के लिए यह मानना ​​मूर्ख नहीं होगा कि कोई घटना क्यों सुन रहा है (घटना को जानने से परे और क्यों)। यदि आप अपनी 'INotifyPropertiesChangedAndChangingWithValues' का पुन: उपयोग करने की योजना बनाते हैं तो विस्तार करें।यदि इसका उपयोग एक बार किया जा रहा है, तो कोई नया इंटरफ़ेस कुछ फायदे के लिए अतिरिक्त काम की तरह लगता है। –

+1

क्योंकि 1) यह हैंडलर ऑर्डर करने के लिए एन समय और घटना नोटिफ़ायर ऑर्डर 1 बार लेता है। 2) घटना अधिसूचना सूचना विशेषज्ञ है। 3) हैंडलर को उस ऑब्जेक्ट में सभी गुणों को ट्रैक करना है, जिसकी संपत्ति बदली गई है, यह निगरानी की जा रही है और खराब डिजाइन है। – Alain

1

नहीं, आपको खरोंच से अपना खुद का बनाना होगा।

मैं अपनी शोध परियोजना, ग्रेनाइट में ऐसा ही करता था, लेकिन मैं इस बात पर आया कि यह लागत के लायक नहीं था। जिन कामों के साथ मैं काम करता हूं उनकी गणना की जाती है, और एक घटना को बढ़ाने के लिए उन्हें दो बार चलाने के लिए बहुत महंगा था।

+0

@ जोनाथन_एलेन: मैंने ऐसा किया, धन्यवाद। – Alain

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