2011-08-19 17 views
17

मेरे पास दो दिनांक फ़ील्ड हैं: स्टार्टडेट और एंडडेट। StartDate EndDate से पहले होना चाहिए।जब उनमें से कोई भी बदलता है तो मैं एकाधिक गुणों को कैसे सत्यापित कर सकता हूं?

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

जब मैं इनमें से कोई भी बदलता हूं तो मैं दोनों दिनांक फ़ील्ड को कैसे सत्यापित कर सकता हूं?

enter image description here

मैं IDataErrorInfo

public string GetValidationError(string propertyName) 
{ 
    switch (propertyName) 
    { 
     case "StartDate": 
      if (StartDate > EndDate) 
       s = "Start Date cannot be later than End Date"; 
      break; 

     case "EndDate": 
      if (StartDate > EndDate) 
       s = "End Date cannot be earlier than Start Date"; 
      break; 
    } 

    return s; 
} 

उपयोग कर रहा हूँ क्योंकि मैं दोनों क्षेत्रों को मान्य करने के जब उनमें से या तो, बदलता है तो उन दोनों को होने एक PropertyChange ईवेंट उत्पन्न की जरूरत है मैं बस एक PropertyChange ईवेंट उत्पन्न नहीं कर सकते क्योंकि एक अनंत लूप में फंस जाएगा।

मुझे दिनांक फ़ील्ड को समाशोधन करने का विचार भी पसंद नहीं है यदि दूसरी तारीख सत्यापन त्रुटि लौटाती है।

+0

बस वहां एक वैकल्पिक दृष्टिकोण फेंकने के लिए, क्या आप नियम तोड़ने पर दोनों बक्से लाल कर सकते हैं? यदि ऐसा है तो आपको केवल एक संपत्ति बदलना होगा। – Josh

+0

@ जोश प्यार करेंगे, लेकिन मुझे नहीं पता कि अलग-अलग गुणों के लिए सत्यापन ईवेंट मैन्युअल रूप से कैसे बढ़ाया जाए – Rachel

+0

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

उत्तर

14

सबसे आसान तरीका दोनों गुण की तरह bathineni suggests

private DateTime StartDate 
{ 
    get { return _startDate; } 
    set 
    { 
     if (_startDate != value) 
     { 
      _startDate = value; 
      RaisePropertyChanged("StartDate"); 
      RaisePropertyChanged("EndDate"); 
     } 
    } 
} 

private DateTime EndDate 
{ 
    get { return _endDate; } 
    set 
    { 
     if (_endDate!= value) 
     { 
      _endDate= value; 
      RaisePropertyChanged("StartDate"); 
      RaisePropertyChanged("EndDate"); 
     } 
    } 
} 

हालांकि मान्य करने की आवश्यकता है कि के लिए सेटर में के लिए एक PropertyChanged अधिसूचना को बढ़ाने के लिए है कि अगर आप के लिए काम नहीं करता है, मैं एक तरह से करने के लिए पता लगा एक साथ गुण का एक समूह को मान्य है, हालांकि अपनी कक्षाओं (मैं EntityFramework और डिफ़ॉल्ट रूप से अपनी कक्षाओं का उपयोग कर रहा दोनों इंटरफेस को लागू)

एक्सटेंशन विधि

के अलावा INotifyPropertyChanging को लागू करना
public static class ValidationGroup 
{ 
    public delegate string ValidationDelegate(string propertyName); 
    public delegate void PropertyChangedDelegate(string propertyName); 

    public static void AddValidationGroup<T>(this T obj, 
     List<string> validationGroup, bool validationFlag, 
     ValidationDelegate validationDelegate, 
     PropertyChangedDelegate propertyChangedDelegate) 
     where T : INotifyPropertyChanged, INotifyPropertyChanging 
    { 

     // This delegate runs before a PropertyChanged event. If the property 
     // being changed exists within the Validation Group, check for validation 
     // errors on the other fields in the group. If there is an error with one 
     // of them, set a flag to true. 
     obj.PropertyChanging += delegate(object sender, PropertyChangingEventArgs e) 
     { 
      if (validationGroup.Contains(e.PropertyName)) 
      { 
       foreach(var property in validationGroup) 
       { 
        if (validationDelegate(property) != null) 
        { 
         validationFlag = true; 
         break; 
        } 
       } 
      } 
     }; 

     // After the Property gets changed, if another field in this group was 
     // invalid prior to the change, then raise the PropertyChanged event for 
     // all other fields in the Validation Group to update them. 
     // Also turn flag off so it doesn't get stuck in an infinite loop 
     obj.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) 
     { 
      if (validationGroup.Contains(e.PropertyName)) 
      { 
       if (validationFlag && validationDelegate(e.PropertyName) == null) 
       { 
        validationFlag = false; 
        foreach(var property in validationGroup) 
        { 
         propertyChangedDelegate(property); 
        } 
       } 
      } 
     }; 
    } 
} 

इसका उपयोग करने के लिए, किसी भी वर्ग के निर्माता को निम्न कॉल जोड़ें जो गुणों के समूह को एक साथ मान्य करना चाहिए।

this.AddValidationGroup(
    new List<string> { "StartDate", "EndDate" }, 
    GetValidationError, OnPropertyChanged); 

मैंने इसे सत्यापन समूह में 3 गुणों के साथ परीक्षण किया है और ऐसा लगता है कि यह ठीक काम करता है।

+0

मुझे आपके जैसा ही समस्या है। क्या आप INotifyPropertyChanging समाधान के साथ गए थे या क्या आपको कोई और तरीका मिला? –

+0

@ Björn मैं इस मामले में 'INotifyPropertyChanging' के साथ गया क्योंकि इंटरफ़ेस पहले से ही इकाई फ्रेमवर्क द्वारा कार्यान्वित किया गया था। अगर ऐसा नहीं होता, तो शायद मैंने संबंधित गुणों के 'सेट' विधियों में अपनी संपत्ति परिवर्तनित घटनाओं को उठाया होगा – Rachel

+0

जानकारी के लिए धन्यवाद। मैंने अपना सत्यापन हटा दिया और अपना कोड बदल दिया ताकि अगर स्टार्टडेट> एंडडेट मैं बस एंडडेट = स्टार्टडेट सेट करूँ। शायद कुछ ऐसा नहीं कर सकता है लेकिन यह मेरे मामले में उपयुक्त है। –

0

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

मेरे कार्यान्वयन के तरीके के लिए this answer देखें। क्षमा करें यह वीबी.नेट में है, लेकिन काफी सरल होना चाहिए।

2

इस चाल का प्रयोग करें, यह बचाता है कि वे एक दूसरे OnPropertyChanged कॉल:

private bool RPCfromStartDate = false; 
private bool RPCfromEndDate = false; 

public string this[string columnName] 
{ 
    get 
    { 
       string result = null; 
       switch (columnName) 
       { 
        case "StartDate": 
         if (StartDate.Date >= EndDate.Date) 
         { 
          result = "Start Date cannot be later than End Date"; 
         } 
         if (!RPCfromEndDate) 
         { 
          RPCfromStartDate = true;        
          OnPropertyChanged("EndDate"); 
          RPCfromStartDate = false; 
         } 
        case "EndDate": 
         if (StartDate.Date >= EndDate.Date) 
         { 
          result = "End Date cannot be earlier than Start Date"; 
         } 
         if (!RPCfromStartDate) 
         { 
          RPCfromEndDate = true;        
          OnPropertyChanged("StartDate"); 
          RPCfromEndDate = false; 
         } 
         break; 
       } 
... 
-1

तुम भी SelectedDateChanged ईवेंट हैंडलर और अद्यतन बंधन की जरूरत की सदस्यता ले सकते।

BindingExpression expression = datePickerStartDate.GetBindingExpression(DatePicker.SelectedDateProperty); 
if (expression != null) 
{ 
    expression.UpdateSource(); 
} 
+0

जैसा कि मैंने अपने प्रश्न में कहा था, यह काम नहीं करता है क्योंकि मेरे पास दो तिथियां हैं और इसलिए यह एक अनंत लूप में फंस जाएगी। – Rachel

+0

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

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

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