2011-08-15 15 views
5

मैं एक WPF आवेदन लिख रहा हूँ और मैं Required फील्ड्स, Range, आदिका मेल DataAnnotations और IDataErrorInfo WPF

मेरे ViewModel कक्षाएं नियमित INotifyPropertyChanged इंटरफ़ेस का उपयोग और मैं मान्य कर सकते हैं जैसी चीजों निर्दिष्ट करने के लिए डाटा व्याख्या का उपयोग करना चाहते हैं के लिए सी # 4 Validator का उपयोग करके पूरी वस्तु आसानी से पर्याप्त है, लेकिन यदि फ़ील्ड ठीक से मान्य नहीं है तो मैं फ़ील्ड को लाल रंग को हाइलाइट करना चाहूंगा। मुझे यह ब्लॉग पोस्ट यहां मिला है (http://blogs.microsoft.co.il/blogs/tomershamam/archive/2010/10/28/wpf-data-validation-using-net-data-annotations-part-ii.aspx) जो IDataErrorInfo को लागू करने के लिए अपना बेस व्यू मॉडल लिखने के बारे में बात करता है और केवल वैलिडेटर का उपयोग करता है, लेकिन कार्यान्वयन वास्तव में संकलित नहीं होता है और न ही मैं देख सकता हूं कि यह कैसे काम करेगा।

/// <summary> 
    /// Validates current instance properties using Data Annotations. 
    /// </summary> 
    /// <param name="propertyName">This instance property to validate.</param> 
    /// <returns>Relevant error string on validation failure or <see cref="System.String.Empty"/> on validation success.</returns> 
    protected virtual string OnValidate(string propertyName) 
    { 
     if (string.IsNullOrEmpty(propertyName)) 
     { 
      throw new ArgumentException("Invalid property name", propertyName); 
     } 

     string error = string.Empty; 
     var value = GetValue(propertyName); 
     var results = new List<ValidationResult>(1); 
     var result = Validator.TryValidateProperty(
      value, 
      new ValidationContext(this, null, null) 
      { 
       MemberName = propertyName 
      }, 
      results); 

     if (!result) 
     { 
      var validationResult = results.First(); 
      error = validationResult.ErrorMessage; 
     } 

     return error; 
    } 

समस्या GetValue प्रदान नहीं की है है: प्रश्न में विधि यह है। वह GetValue के बारे में बात कर सकता है जो तब आता है जब आप DependencyObject प्राप्त करते हैं, लेकिन वाक्यविन्यास अभी भी काम नहीं करता है (यह आपको पैरामीटर के रूप में DependencyProperty पास करने की अपेक्षा करता है) लेकिन मैं नियमित सीएलआर गुणों का उपयोग कर रहा हूं OnPropertyChanged("MyProperty") को सेटटर पर बुलाया जा रहा है।

क्या IDataErrorInfo इंटरफ़ेस को सत्यापन कनेक्ट करने का कोई अच्छा तरीका है?

उत्तर

5

अपने उपरोक्त कोड को शुरुआती बिंदु के रूप में उपयोग करके मुझे यह IDataErrorInfo के माध्यम से मिल रहा है।

आपकी समस्या संपत्ति के मूल्य को प्राप्त करने के आसपास केंद्रित होती है जब आपके पास केवल संपत्ति का नाम होता है, प्रतिबिंब यहां सहायता कर सकता है।

public string this[string property] 
{ 
    get 
    { 
     PropertyInfo propertyInfo = this.GetType().GetProperty(property); 
     var results = new List<ValidationResult>(); 

     var result = Validator.TryValidateProperty(
           propertyInfo.GetValue(this, null), 
           new ValidationContext(this, null, null) 
           { 
            MemberName = property 
           }, 
           results); 

     if (!result) 
     { 
     var validationResult = results.First(); 
     return validationResult.ErrorMessage; 
     } 

     return string.Empty; 
    } 
} 
+0

यह बहुत कुछ है जो मैंने किया है, लेकिन यदि आप दृश्य मॉडल में निर्भरता गुण रखते हैं तो यह काम नहीं करेगा, इसलिए आपको दोनों तरीकों से प्रयास करना होगा। यह उतना ही सुरुचिपूर्ण नहीं है जितना कि मैंने आशा की थी लेकिन कभी-कभी आपको यही जाना पड़ता है। –

1

मैं जानता हूँ कि इस पोस्ट पुरानी है, लेकिन मैं हाल ही में, इस पोस्ट की मदद से इस समस्या का समाधान करते हुए रास्ते में कुछ अनुकूलन बना रही है। मैं IDATErrorInfo के मेरे ViewModelBase के कार्यान्वयन को साझा करना चाहता हूं। यह संपत्ति गेटर्स के लिए संकलित अभिव्यक्तियों का उपयोग करता है जो संपत्ति मूल्य पहुंच को गति देता है। जब स्मृति स्मृति में लोड होता है तो मैं बैकग्राउंड थ्रेड पर अभिव्यक्ति संकलन को भी बंद कर देता हूं। उम्मीद है कि यह ऑनवालिडेट को पहली कॉल से पहले संकलन को समाप्त करता है क्योंकि अभिव्यक्ति संकलन थोड़ा धीमा हो सकता है। धन्यवाद और चीयर्स।

public abstract class ViewModelBase<TViewModel> : IDataErrorInfo 
    where TViewModel : ViewModelBase<TViewModel> 
{ 
    string IDataErrorInfo.Error 
    { 
     get { throw new NotSupportedException("IDataErrorInfo.Error is not supported, use IDataErrorInfo.this[propertyName] instead."); } 
    } 

    string IDataErrorInfo.this[string propertyName] 
    { 
     get { return OnValidate(propertyName, propertyGetters.Result[propertyName]((TViewModel)this)); } 
    } 

    private static Task<Dictionary<string, Func<TViewModel, object>>> propertyGetters = Task.Run(() => 
    { 
     return typeof(TViewModel).GetProperties() 
      .Select(propertyInfo => 
      { 
       var viewModel = Expression.Parameter(typeof(TViewModel)); 
       var property = Expression.Property(viewModel, propertyInfo); 
       var castToObject = Expression.Convert(property, typeof(object)); 
       var lambda = Expression.Lambda(castToObject, viewModel); 

       return new 
       { 
        Key = propertyInfo.Name, 
        Value = (Func<TViewModel, object>)lambda.Compile() 
       }; 
      }) 
      .ToDictionary(pair => pair.Key, pair => pair.Value); 
    }); 

    protected virtual string OnValidate(string propertyName, object propertyValue) 
    { 
     var validationResults = new List<ValidationResult>(); 

     var validationContext = new ValidationContext(this, null, null) { MemberName = propertyName }; 

     if (!Validator.TryValidateProperty(propertyValue, validationContext, validationResults)) 
     { 
      return validationResults.First().ErrorMessage; 
     } 

     return string.Empty; 
    } 
} 
संबंधित मुद्दे