2013-09-01 7 views
8

Sto provando a fare qualcosa che in precedenza avrei assunto sarebbe stato abbastanza semplice: utilizzare il valore di un controllo nella regola di convalida di un altro. La mia applicazione ha una varietà di parametri che l'utente può inserire, i parametri specifici in questione qui definiscono i punti di inizio e fine di un intervallo e l'utente imposta i valori attraverso una casella di testo.Regole di convalida che utilizzano il valore di un altro controllo

I due controlli in questione sono le iniziali e finali caselle di testo, e le seguenti condizioni devono essere controllate in validazione:

  1. Valore iniziale deve essere maggiore o uguale a un valore arbitrario
  2. valore finale deve essere minore o uguale a un valore arbitrario
  3. valore iniziale deve essere minore o uguale al valore terminare

Le prime due condizioni ho già accompl mentata. Il terzo è molto più difficile da implementare, perché non posso accedere al valore della casella di testo finale dal validatore. Anche se potessi, ci sono cinque diversi intervalli (ciascuno con la propria casella di testo iniziale e finale) che sto provando a convalidare, e ci deve essere una soluzione più elegante della creazione di una regola di convalida per ognuno.

ecco il codice XAML rilevanti:

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:validators="clr-namespace:CustomValidators" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 

    <TextBox Name="textboxStart" Grid.Row="0"> 
     <TextBox.Text> 
      <Binding Path="Start" UpdateSourceTrigger="PropertyChanged"> 
       <Binding.ValidationRules> 
        <validators:MeasurementRangeRule Min="1513" Max="1583"/> 
       </Binding.ValidationRules> 
      </Binding> 
     </TextBox.Text> 
    </TextBox> 

    <TextBox Name="textboxEnd" Grid.Row="1"> 
     <TextBox.Text> 
      <Binding Path="End" UpdateSourceTrigger="PropertyChanged"> 
       <Binding.ValidationRules> 
        <validators:MeasurementRangeRule Min="1513" Max="1583"/> 
       </Binding.ValidationRules> 
      </Binding> 
     </TextBox.Text> 
    </TextBox> 
</Grid> 

Ed ecco il relativo codice C#:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Runtime.CompilerServices; 
using System.ComponentModel; 
using System.Globalization; 

namespace WpfApplication1 { 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window { 
     public MainWindow() { 
      InitializeComponent(); 
     } 

     private decimal _start; 
     private decimal _end; 
     public event PropertyChangedEventHandler PropertyChanged; 

     public decimal Start { 
      get { return _start; } 
      set { 
       _start = value; 
       RaisePropertyChanged(); 
      } 
     } 

     public decimal End { 
      get { return _end; } 
      set { 
       _end = value; 
       RaisePropertyChanged(); 
      } 
     } 

     private void RaisePropertyChanged ([CallerMemberName] string propertyName = "") { 
      if (PropertyChanged != null) { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 

namespace CustomValidators { 

    public class MeasurementRangeRule : ValidationRule { 
     private decimal _min; 
     private decimal _max; 

     public decimal Min { 
      get { return _min; } 
      set { _min = value; } 
     } 

     public decimal Max { 
      get { return _max; } 
      set { _max = value; } 
     } 

     public override ValidationResult Validate (object value, CultureInfo cultureInfo) { 
      decimal measurementParameter = 0; 

      try { 
       if (((string) value).Length > 0) 
        measurementParameter = Decimal.Parse((String) value); 
      } catch (Exception e) { 
       return new ValidationResult(false, "Illegal characters or " + e.Message); 
      } 

      if ((measurementParameter < Min) || (measurementParameter > Max)) { 
       return new ValidationResult(false, 
        "Out of range. Enter a parameter in the range: " + Min + " - " + Max + "."); 
      } else { 
       return new ValidationResult(true, null); 
      } 
     } 
    } 
} 

La questione legata here sembra essere rilevante, ma non riesco a capire le risposte fornite.

Grazie ...

+0

Hai guardato IDataErrorInfo o un BindingGroup? – Shoe

+0

@Jim Ho guardato IDataErrorInfo, ristrutturato il mio codice per incapsulare le proprietà rilevanti (inizio, fine, min e max) nella loro stessa classe, e quindi implementato IDataErrorInfo. Quella configurazione ha funzionato come un fascino, molto apprezzato per il puntatore. Domani pubblicherò la risposta. –

risposta

4

Per qualsiasi che potrebbe affrontare questo problema, è molto più facile da implementare IDataErrorInfo per convalidare gli errori in generale, e per realizzare la convalida contro altri controlli in qualche raggruppamento logico. Ho incapsulato le proprietà pertinenti (inizio, fine, min e max) in una singola classe, ho associato i controlli a tali proprietà e quindi ho utilizzato l'interfaccia IDataErrorInfo per la convalida. Codice in materia è al di sotto ...

XAML:

<TextBox Name="textboxStart" Grid.Row="0" Text="{Binding Path=Start, ValidatesOnDataErrors=True}" Margin="5"/> 
    <TextBox Name="textboxEnd" Grid.Row="1" Text="{Binding Path=End, ValidatesOnDataErrors=True}" Margin="5"/> 
</Grid> 

C#:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.Runtime.CompilerServices; 
using System.ComponentModel; 

namespace WpfApplication1 { 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window { 
     public MainWindow() { 
      InitializeComponent(); 

      Parameter testParameter = new Parameter(0, 10); 
      testGrid.DataContext = testParameter; 
     } 
    } 

    public class Parameter: INotifyPropertyChanged, IDataErrorInfo { 
     private decimal _start, _end, _min, _max; 
     public event PropertyChangedEventHandler PropertyChanged; 

     public Parameter() { } 

     public Parameter (decimal min, decimal max) { 
      this.Min = min; 
      this.Max = max; 
     } 

     public decimal Start { 
      get { return _start; } 
      set { 
       _start = value; 
       //RaisePropertyChanged for both Start and End, because one may need to be marked as invalid because of the other's current setting. 
       //e.g. Start > End, in which case both properties are now invalid according to the established conditions, but only the most recently changed property will be validated 
       RaisePropertyChanged(); 
       RaisePropertyChanged("End"); 
      } 
     } 

     public decimal End { 
      get { return _end; } 
      set { 
       _end = value; 
       //RaisePropertyChanged for both Start and End, because one may need to be marked as invalid because of the other's current setting. 
       //e.g. Start > End, in which case both properties are now invalid according to the established conditions, but only the most recently changed property will be validated 
       RaisePropertyChanged(); 
       RaisePropertyChanged("Start"); 
      } 
     } 

     public decimal Min { 
      get { return _min; } 
      set { _min = value; } 
     } 

     public decimal Max { 
      get { return _max; } 
      set { _max = value; } 
     } 

     private void RaisePropertyChanged ([CallerMemberName] string propertyName = "") { 
      if (PropertyChanged != null) { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     public string Error { 
      get { return string.Empty; } 
     } 

     public string this[string columnName] { 
      get { 
       string result = string.Empty; 

       switch (columnName) { 
        case "Start": 
         if (Start < Min || Start > Max || Start > End) { 
          result = "Out of range. Enter a value in the range: " + Min + " - " + End + "."; 
         } 
         break; 
        case "End": 
         if (End < Min || End > Max || End < Start) { 
          result = "Out of range. Enter a value in the range: " + Start + " - " + Max + "."; 
         } 
         break; 
       }; 

       return result; 
      } 
     } 
    } 
} 
Problemi correlati