2010-06-24 2 views
8

Attualmente sto esaminando la convalida della mia app WPF e ho visto la menzione di IDataErrorInfo. Tuttavia ci sono poche guide su come usarlo e peggio non ce ne sono che spiegano come funziona.Come funziona IDataErrorInfo?

Sul sito MSND.com questo è Givin' MSDN

public class Person : IDataErrorInfo 
{ 
    private int age; 
    public int Age 
    { 
     get { return age; } 
     set { age = value; } 
    } 

    public string Error 
    { 
     get 
     { 
      return null; 
     } 
    } 

    public string this[string name] 
    { 
     get 
     { 
      string result = null; 
      if (name == "Age") 
      { 
       if (this.age < 0 || this.age > 150) 
       { 
        result = "Age must not be less than 0 or greater than 150."; 
       } 
      } 
      return result; 
     } 
    } 
} 

io vedere che cosa sta succedendo qui, ma non ho idea di quello che fa veramente per i miei dati.

Quando vengono utilizzate queste 2 proprietà? Diciamo che qualcuno imposta Age come 400: viene chiamato il setter sulla proprietà. L'errore non gli impedirà di essere impostato? In caso contrario, si avverte che il numero non è corretto, come impedire a qualcuno di salvare le informazioni così com'è? Non c'è il metodo IsValid() da controllare, c'è?

Mi piacerebbe sapere cosa succede dietro le tende.

risposta

6

La proprietà Error non viene in genere utilizzata, ma è necessario definirla per implementare l'interfaccia. Come diceva il deciclone, la validazione non impedirà alla proprietà di essere impostata con il valore sbagliato, ma è possibile impostare la proprietà su un valore predefinito. Lascia che ti mostri come lo sto usando. Ho un paio di TextBox es che devo convalidare i valori che hanno. Invece di mostrare un MessageBox con l'errore quando viene chiamato il set, voglio adottare un approccio "webly": voglio che il bordo e lo sfondo dello TextBox siano rossi quando viene impostato un valore non valido e il tooltip di su mostra l'errore che ha ottenuto.

Questo è il mio XAML per TextBox:

<converters:ValidationConverter x:Key="validationConverter"/> 
<Style x:Key="TestStepTextBox" TargetType="{x:Type TextBox}"> 
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TextBox}"> 
       <Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> 
        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
       </Border> 
       <ControlTemplate.Triggers> 
        <Trigger Property="Validation.HasError" Value="true"> 
         <Setter Property="ToolTip" 
           Value="{Binding RelativeSource={RelativeSource Self}, 
           Converter={StaticResource validationConverter}, Path=(Validation.Errors)}"/> 
         <Setter Property="Background" Value="#33FF342D"/> 
         <Setter Property="BorderBrush" Value="#AAFF342D"/> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

<TextBox Name="txtRunAfter" Text="{Binding RunAfter, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource TestStepTextBox}"/> 
<TextBox Name="txtStopAfter" Text="{Binding StopAfter, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource TestStepTextBox}"/> 

Un molto importante nota sul convertitore. Stavo ricevendo un'eccezione quando ho inserito un valore non valido e quindi ho impostato un buon valore. In qualche modo, forse correlato ad avere UpdateSourceTrigger=PropertyChanged, c'era un momento in cui la proprietà HasError era vera ma non c'erano errori impostati (vedere link). Così qui è il codice per il convertitore:

public class ValidationConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     ReadOnlyObservableCollection<ValidationError> errors = value as ReadOnlyObservableCollection<ValidationError>; 
     if (errors == null) return value; 
     if (errors.Count > 0) 
     { 
      return errors[0].ErrorContent; 
     } 
     return ""; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException("This method should never be called"); 
    } 
} 

Per evitare il valore invaled vengano salvati al mio livello di modello sto usando lo stesso metodo per controllare se devo commettere i dati al modello. Se il valore non è valido, imposto la proprietà e non richiama un insieme della proprietà nel modello. Controllare il codice:

private int _runAfter = 0; 
public int RunAfter 
{ 
    get 
    { 
     return _runAfter; 
    } 

    set 
    { 
     if (_runAfter != value) 
     { 
      _runAfter = value; 
      OnPropertyChanged("RunAfter"); 

      if (validateRunAfter() == null) 
       setRunAfter(); //sets the property value to the model layer 
     } 
    } 
} 

string IDataErrorInfo.this[string columnName] 
{ 
    get 
    { 
     string message = null; 
     if (columnName == "RunAfter") 
      message = validateRunAfter(); 
     //... 
     return message; 
    } 
} 

private string validateRunAfter() 
{ 
    if (value >= _order) 
     return "Run After value must be less than its Step Order (#) value."; 

    return null; 
} 
+0

Grazie, non ho avuto il tempo di verificarlo correttamente ma fornirò la risposta corretta se va tutto bene;) –

2

Quello che so di IDataErrorInfo è esso viene utilizzato solo UI scopi. Quello che fa è fornire un modo semplice per associare i messaggi di errore allo WPF UI. Poiché WPF UI "identifica" gli oggetti che implementano IDataErrorInfo come INotifyPropertyChanged, non è necessario scrivere codice aggiuntivo per mostrare i messaggi di errore nello UI.

Un'ultima cosa, non si fermerà dall'essere impostato il valore sbagliato. Dirà semplicemente allo WPF UI (quando WPF UI chiama l'indicizzatore che fornisce il nome della proprietà) che il valore in una proprietà specifica non è valido.

+0

aggiungere a questo, IDataErrorInfo vale per ASP.NET MVC UI come pure, in quanto è da System.ComponentModel http: //www.asp.net/mvc/tutorial/versioni precedenti/modelli- (dati)/validating-with-the-idataerrorinfo-interface-cs – Sai