2011-08-19 4 views
17

Ho due campi data: StartDate e EndDate. StartDate deve essere precedente a EndDate.Come posso convalidare più proprietà quando una di esse cambia?

Se l'utente modifica la data di inizio su un valore superiore a EndDate, viene visualizzato un bordo rosso attorno a DatePicker e viceversa. Se l'utente cambia la seconda casella in modo che l'intervallo di date sia corretto, la prima casella ha ancora l'errore di convalida.

Come posso convalidare entrambi i campi data quando uno di essi cambia?

enter image description here

sto usando 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; 
} 

Non posso semplicemente sollevare un evento PropertyChange perché ho bisogno di convalidare entrambi i campi, quando uno di loro cambia, in modo da avere entrambi sollevare un evento PropertyChange per l'altro si bloccherà in un loop infinito.

Inoltre, non mi piace l'idea di cancellare il campo Data se l'altra data restituisce un errore di convalida.

+0

Solo per lanciare un approccio alternativo là fuori, puoi rendere entrambe le caselle rosse quando una regola è rotta? Se è così, dovrai solo aumentare un evento di proprietà. – Josh

+0

@Josh Mi piacerebbe, ma non so come aumentare manualmente l'evento di convalida per le singole proprietà – Rachel

+0

Ho smesso di utilizzare Eventi di convalida.Ho avuto troppi problemi con loro, dove penso che dovrebbero sparare e loro no o fanno fuoco e il confine non evidenzia. Uso uno stile bordo rosso associato a una rappresentazione booleana valida. Lego anche il suggerimento a una proprietà del messaggio. Quindi, quando un valore cambia, lo convalido e imposto le proprietà in modo appropriato. – Josh

risposta

14

Il modo più semplice è quello di sollevare una notifica PropertyChanged per la setter per entrambe le proprietà che devono essere validati come 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"); 
     } 
    } 
} 

Tuttavia, se questo non funziona per voi, ho capito un modo per convalidare un gruppo di proprietà di insieme, anche se le vostre classi devono implementare INotifyPropertyChanging oltre a INotifyPropertyChanged (sto usando EntityFramework e per impostazione predefinita le loro classi implementare entrambe le interfacce)

Metodo di estensione

Per utilizzarlo, aggiungere la seguente chiamata al costruttore di qualsiasi classe che dovrebbe convalidare un gruppo di proprietà insieme.

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

Ho provato questo con un massimo di 3 proprietà in un gruppo di convalida e sembra funzionare correttamente.

+0

Sto avendo lo stesso identico problema di te. Sei andato con la soluzione INotifyPropertyChanging o hai trovato un altro modo? –

+0

@ Björn Sono andato con 'INotifyPropertyChanging' in questo caso perché l'interfaccia era già implementata da Entity Framework. Se non fosse stato, probabilmente avrei alzato i miei eventi PropertyChanged nei metodi 'set' delle proprietà correlate – Rachel

+0

Grazie per le informazioni. Ho rimosso la convalida e modificato il mio codice in modo che se StartDate> EndDate ho semplicemente impostato EndDate = StartDate. Forse non è qualcosa che tutti possono fare, ma è adatto nel mio caso. –

0

In genere aggiungo tutti i miei errori di convalida a un dizionario e il modello di convalida si iscrive a tale tramite il nome della proprietà. In ogni gestore di eventi modificati di proprietà, posso controllare qualsiasi numero di proprietà e aggiungere o rimuovere il loro stato di convalida se necessario.

Controllare this answer per l'aspetto della mia implementazione. Scusa è in VB.NET, ma dovrebbe essere abbastanza semplice.

2

Utilizzare questo trucco, impedisce che chiamano OnPropertyChanged vicenda:

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

Puoi anche iscriverti al gestore di eventi SelectedDateChanged e l'aggiornamento necessari vincolante.

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

Come ho detto nella mia domanda, questo non funziona perché ho due date e quindi resterà bloccato in un ciclo infinito. – Rachel

+0

Non sono sicuro di cosa ti stia confondendo. Quando la modifica di StartDate viene modificata, si aggiorna il binding EndDate (viene eseguita solo la convalida, non viene apportata alcuna modifica). Al termine della modifica di endDate, si aggiorna il bind StartDate. Non dovrebbero verificarsi loop infiniti. –