Walidacja danych ma na celu ograniczenie wprowadzania przez użytkownika nieprawidłowych danych i komunikacja nieprawidłowości na bieżąco.
WPF umożliwia zdefiniowanie zasad, walidacji danej właściwości. każda taka zasada to implementacja klasy
ValidationRule:
Code:
namespace WpfExample
{
public class IsIntValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.GlobalizationCultureInfo cultureInfo)
{
if (value == null)
{
return new ValidationResult(false, "Wartość nie może być nullem");
}
var valueAsString = value.ToString();
int valueInt;
if (int.TryParse(valueAsString, out valueInt))
{
return ValidationResult.ValidResult;
}
return new ValidationResult(false, "Brak możliwości konwersji na int");
}
}
}
Code:
<Window x:Class="WpfExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfExample"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="100">
<TextBox.Text>
<Binding Path="Value">
<Binding.ValidationRules>
<local:IsIntValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="Button" HorizontalAlignment="Left" Margin="161,128,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
Przetwarzanie zasad następuje w kolejności w której zostały one zdefiniowane w kodzie XAML. Jeżeli walidacja przebiegnie pomyślnie, nic nadzwyczajnego nie dzieje się i interfejs programu nie zmienia zachowania. W przypadku gdy któraś z reguł nie przejdzie:
- element, którego walidacja nie przeszła zostaje otoczony czerwoną ramką
- zostaje ustawiona falga Validaton.HasError
- do kolekcji Errors zostaje dodany nowy obiekt typu ValidationError
- jeżeli jest ustawiona flaga Binding.NotifyOnValidationError - zdarzenie Validation.Error zostaje wywołane
- zbindowana właściwość w źródle nie zostanie zaktualizowana
Implementacja tego rozwiązania jest bardzo prosta i zgodnie z przedstawionym przykładem powyżej wymaga:
- stworzenie klasy która dziedziczy po ValidationRule
- nadpisujemy metodę Validate
Metoda
Validate przyjmuje jako parametr wartość obiektu do walidacji i zwraca obiekt klasy
ValidationResult, który posiada następujące właściwości:
- IsValid - flaga informująca czy walidacja przebiegła pomyślnie
- ErrorContent - informacje o błędzie w przypadku gdy walidacja nie przebiegła pomyślnie
Jeżeli chcemy sprawdzić czy walidacja zawiodła z powodu problemów z bindowaniem, możemy skorzystać z gotowej zasady
ExceptionValidationRule.
Obsługa błędów walidacji
Błędy w walidacji należy obsłużyć. Czerwona obwódka wokół błędnie wprowadzonej wartości może być nie wystarczająca dla użytkownika.
Jeżeli element, który jest zbindowany ma włączoną walidację, w przypadku błędu zostanie wywołane zdarzenie
Validation.Error. Zdarzenie to jako jeden z parametrów przyjmuje obiekt klasy
ValidationErrorEventArgs. Klasa ta zawiera dwie ważne właściwości:
- Action - flaga mówiąca czy zdarzenie jest wywoływane dla nowego błędu, czy też podczas usuwania starego
- Error - opis błędu
Obiekt Error zawiera następujące informacje o błędzie:
- BindingInError - referencja do bindingu który wywołał błąd
- ErrorContent - opis pochodzący z obiektu ValidationRule
- Exception
- RuleInError - referencja do obiektu ValidationRule, który spowodował błąd
Aby zdarzenie Validation.Error było wywołane, należy ustawić flagę NotifyOnValidationError. Zdarzenie to jest typu bubbling, zapoczątkowane jest więc w elemencie którego dotyczy, a następnie przechodzi w górę drzewa aż do momentu obsłużenia.
Przykład obsługi błędu:
Code:
<Window x:Class="WpfExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfExample"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Validation.Error="TextBox_Error_1">
<TextBox.Text>
<Binding Path="Value" NotifyOnValidationError="True">
<Binding.ValidationRules>
<local:IsIntValidationRule/>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="Button" HorizontalAlignment="Left" Margin="161,128,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
Code:
private void TextBox_Error_1(object sender, ValidationErrorEventArgs e)
{
switch (e.Action)
{
case ValidationErrorEventAction.Added:
MessageBox.Show(e.Error.ErrorContent.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
break;
case ValidationErrorEventAction.Removed:
System.Diagnostics.Trace.WriteLine("Błąd walidacji został usunięty");
break;
}
}
Brak komentarzy:
Prześlij komentarz