2012-03-21 19 views
11

WPF'de hala doğrulama ile mücadele ediyorum.İlk Yükte Doğrulama Bağlaması

Metin kutusuna metin girilmesini gerektiren özel bir doğrulama kuralım var, yani zorunlu bir alan kısıtlaması zorlar. Pencere ilk yüklendiğinde, TextBox metin olduğunda (beklediğiniz gibi) o

<TextBox local:Masking.Mask="^[a-zA-Z0-9]*$" x:Name="CameraIdCodeTextBox" Grid.Row="1" Grid.Column="1"> 
    <Binding Path="CameraIdCode" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True" ValidatesOnExceptions="True"> 
    <Binding.ValidationRules> 
     <localValidation:RequiredFieldRule /> 
    </Binding.ValidationRules> 
    </Binding> 
</TextBox> 

sorundur. Ancak, Text özelliği, ViewModel'deki bir özelliğe bağlı durumdadır ve bu nedenle, doğrulama kuralı Windows ile ilgili bir sorun olduğunu belirten doğrulama kuralıdır - kullanıcı bir iş kuralını ihlal etme fırsatından bile önce.

Bu daha önce çözülmüş bir sorun mu? Bunu deneyimleyen ilk kişi olamam. Eminim genç oyuncular için bir tuzaktır.

+0

Şunları yapabilirsiniz ... UpdateSourceTrigger = "LostFocus" –

+0

Bir doğrulama grubu oluşturabilir ve yalnızca kullanıcı bir alan için ilk değişiklik yaptığında etkinleştirebilirsiniz. –

+0

@AngelWPF Bunu denedim. Pencere yüklendiğinde hala ilk bağda doğrular. – onefootswill

cevap

0

Bir süre oldu ve ben bu soruyu güncellenmiş olması gerekirdi. Ben Ian Griffths (bir O'Reilly kitap) tarafından bir WPF kitapta bulunan bir sınıfı kullanarak çözüldü:

<TextBox local:Masking.Mask="^[0-9]*$" IsEnabled="{Binding Path=LocationNumberEnabled}" Grid.Row="1" Grid.Column="3"> 
    <Binding Path="LocationNumber" Mode="TwoWay" UpdateSourceTrigger="LostFocus" NotifyOnValidationError="True" ValidatesOnExceptions="True"> 
     <Binding.ValidationRules> 
      <localValidation:PositiveNumberRule /> 
      <localValidation:RequiredFieldRule /> 
     </Binding.ValidationRules> 
    </Binding>      
</TextBox> 

:

public static class Validator 
{ 
    /// <summary> 
    /// This method forces WPF to validate the child controls of the control passed in as a parameter. 
    /// </summary> 
    /// <param name="parent">Type: DependencyObject. The control which is the descendent root control to validate.</param> 
    /// <returns>Type: bool. The validation result</returns> 
    public static bool IsValid(DependencyObject parent) 
    { 
     // Validate all the bindings on the parent 
     bool valid = true; 
     LocalValueEnumerator localValues = parent.GetLocalValueEnumerator(); 
     while (localValues.MoveNext()) 
     { 
      LocalValueEntry entry = localValues.Current; 
      if (BindingOperations.IsDataBound(parent, entry.Property)) 
      { 
       Binding binding = BindingOperations.GetBinding(parent, entry.Property); 
       foreach (ValidationRule rule in binding.ValidationRules) 
       { 
        ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null); 
        if (!result.IsValid) 
        { 
         BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property); 
         Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null)); 
         valid = false; 
        } 
       } 
      } 
     } 

     // Validate all the bindings on the children 
     for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(parent, i); 
      if (!IsValid(child)) 
      { 
       valid = false; 
      } 
     } 

     return valid; 
    } 

} 

Sonra görünümünde, aşağıdaki yapılandırmayı vardı Bir çekicilik gibi çalıştı! Manuel olarak doğrulamak istediğim her zaman IsValid yöntemini aradım. bir düğmeye basın.

0

Bunun için birkaç desen var. Ben genellikle BeginInit() ve EndInit() oluşturmanızı gerektiren sınıf/Model ISupportInitialize arabirimini uygularım. Bu yöntemlerde yalnızca _isInitializing özel bir bool'u doğru veya yanlış olarak ayarladım. görünümü modelinde

veya/oluşturmayı/modeliniz/sınıf onu başlangıç ​​ve bitiş init ile sarın doldurmak zaman:

var o = new SampleObject(); 
o.BeginInit() 
o.StartDate = DateTime.Now; //just some sample property... 
o.EndInit(); 

Öyleyse senin ValidationRule çağrılır nasıl bağlı olarak, durumunu kontrol edebilir Doğrulamanız gerekip gerekmediğini görmek için _isInitializing numaralı telefon numaranız. Eğer ISupportInitialize ile rahatsız etmek istemiyorsanız

[CustomValidator("ValidateStartDate")] 
public DateTime StartDate 
{ get ... 
{ 
    set 
    { 
     if(_startDate == value) return; 
     _startDate = value; 
     if(_isInitializing) return; 
     RaisePropertyChange(() => StartDate); 
     }.. 

, o zaman gereken tüm değerler geçirmek:

Son zamanlarda kullanıyorum nitelik yüzden böyle bir şey yapabileceğini PropertyChanged hangi yangın doğrulayıcıları İnşaat sırasında mülkünüz mal değil. özellikleriniz üzerinde ilk defa alıcılar sorgular Bağlama ve değerlerini alacak ve herşeyi mülkiyet setter geçer ve valide olsun:

//c-tor 
public MyObject(DateTime start) 
{ 
    _startDate = start; 
} 
İlgili konular