ventanas - wpf visual studio
ValidaciĆ³n de WPF para todo el formulario (5)
Sugeriría mirar la interfaz IDataErrorInfo en su objeto comercial. También eche un vistazo a este artículo: cuadro de texto de autovalidación
Me he sentido muy decepcionado con el sistema de validación de WPF. ¡De todas formas! ¿Cómo puedo validar el formulario completo haciendo clic en el "botón"?
¡Por alguna razón todo en WPF es tan complicado! Puedo hacer la validación en 1 línea de código en ASP.NET que requiere como 10-20 líneas de código en WPF !!
Puedo hacer esto usando mi propio framework ValidationEngine:
Customer customer = new Customer();
customer.FirstName = "John";
customer.LastName = String.Empty;
ValidationEngine.Validate(customer);
if (customer.BrokenRules.Count > 0)
{
// do something display the broken rules!
}
La descripción de tu problema es un poco vaga para mí. Quiero decir, no estoy exactamente seguro de cuál es tu dificultad. Suponiendo que DataContext es una especie de presentador o controlador que tiene una propetry que representa la instancia del cliente, y ValidateCommand es una propiedad de tipo ICommand:
<StackPanel>
<TextBox Text="{Binding CurrentCustomer.FirstName}" />
<TextBox Text="{Binding CurrentCustomer.LastName}" />
<Button Content="Validate"
Command="{Binding ValidateCommand}"
CommandParameter="{Binding CurrentCustomer}" />
<ItemsControl ItemsSource="{Binding CurrentCustomer.BrokenRules}" />
</StackPanel>
Este XAML está realmente simplificado, por supuesto, y hay otras maneras de hacerlo. Como desarrollador web que ahora está muy involucrado con WPF, encuentro que la mayoría de las tareas de este tipo son mucho más fáciles en WPF.
Una aplicación WPF debe deshabilitar el botón para enviar un formulario si la información ingresada no es válida. Puede lograr esto implementando la interfaz IDataErrorInfo en su objeto comercial, utilizando Vinculaciones con ValidatesOnDataErrors
=true
. Para personalizar el aspecto de los controles individuales en el caso de errores, establezca Validation.ErrorTemplate
.
XAML:
<Window x:Class="Example.CustomerWindow" ...>
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Save"
CanExecute="SaveCanExecute"
Executed="SaveExecuted" />
</Window.CommandBindings>
<StackPanel>
<TextBox Text="{Binding FirstName, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding LastName, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
<Button Command="ApplicationCommands.Save" IsDefault="True">Save</Button>
<TextBlock Text="{Binding Error}"/>
</StackPanel>
</Window>
Esto crea una Window
con dos TextBox
es donde puede editar el nombre y apellido de un cliente. El botón "Guardar" solo está habilitado si no se han producido errores de validación. El TextBlock
debajo del botón muestra los errores actuales, por lo que el usuario sabe qué sucede.
La ErrorTemplate
predeterminada es un borde rojo fino alrededor del control erróneo. Si eso no encaja en su concepto visual, consulte Validación en el artículo de Windows Presentation Foundation en CodeProject para conocer en profundidad qué se puede hacer al respecto.
Para que la ventana funcione realmente, tiene que haber una infraestructura de bits en la Ventana y el Cliente.
Código detrás
// The CustomerWindow class receives the Customer to display
// and manages the Save command
public class CustomerWindow : Window
{
private Customer CurrentCustomer;
public CustomerWindow(Customer c)
{
// store the customer for the bindings
DataContext = CurrentCustomer = c;
InitializeComponent();
}
private void SaveCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ValidationEngine.Validate(CurrentCustomer);
}
private void SaveExecuted(object sender, ExecutedRoutedEventArgs e)
{
CurrentCustomer.Save();
}
}
public class Customer : IDataErrorInfo, INotifyPropertyChanged
{
// holds the actual value of FirstName
private string FirstNameBackingStore;
// the accessor for FirstName. Only accepts valid values.
public string FirstName {
get { return FirstNameBackingStore; }
set {
FirstNameBackingStore = value;
ValidationEngine.Validate(this);
OnPropertyChanged("FirstName");
}
}
// similar for LastName
string IDataErrorInfo.Error {
get { return String.Join("/n", BrokenRules.Values); }
}
string IDataErrorInfo.this[string columnName]
{
get { return BrokenRules[columnName]; }
}
}
Una mejora obvia sería mover la implementación de IDataErrorInfo
a la jerarquía de clases, ya que solo depende de ValidationEngine
, pero no del objeto comercial.
Si bien esto es más un código que el simple ejemplo que proporcionó, también tiene un poco más de funcionalidad que solo verificar la validez. Esto le proporciona indicaciones precisas y actualizadas automáticamente al usuario sobre los problemas de validación y desactiva automáticamente el botón "Guardar" siempre que el usuario intente ingresar datos no válidos.
Es posible que le interese la aplicación de ejemplo BookLibrary del WPF Application Framework (WAF) . Muestra cómo usar la validación en WPF y cómo controlar el botón Guardar cuando existen errores de validación.
ValidatesOnDataError se utiliza para validar las reglas comerciales en comparación con los modelos de vista, y se validará solo si el enlace se realiza correctamente.
Es necesario aplicar ValidatesOnExceptions junto con ValidatesOnDataError para manejar los escenarios en los que wpf no puede realizar el enlace debido a la falta de coincidencia del tipo de datos, digamos que desea vincular un TextBox a la propiedad Age (integer) en su modelo de vista
<TextBox Text="{Binding Age, ValidatesOnDataErrors=true, UpdateSourceTrigger=PropertyChanged}" />
Si el usuario ingresa una entrada inválida escribiendo alfabetos en lugar de números como edad, digamos xyz, wpf databinding ignorará silenciosamente el valor ya que no puede vincular xyz a Age, y el error de enlace se perderá a menos que el enlace esté decorado con ValidatesOnExceptions
<TextBox Text="{Binding Age, ValidatesOnDataErrors=true, ValidatesOnExceptions="True", UpdateSourceTrigger=PropertyChanged}" />
ValidatesOnException utiliza el manejo de excepciones predeterminado para errores de enlace usando ExceptionValidationRule, la sintaxis anterior es una forma abreviada para lo siguiente
<TextBox>
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Puede definir sus propias reglas para validar contra la entrada del usuario derivando de ValidationRule e implementando el método Validate, NumericRule en el siguiente ejemplo
<TextBox.Text>
<Binding Path="Age" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<rules:NumericRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
Las reglas de validación deben ser genéricas y no estar vinculadas a los negocios, ya que lo último se logra a través de IDataErrorInfo y ValidatesOnDataError.
La sintaxis anterior es bastante desordenada en comparación con la sintaxis de enlace de una línea que tenemos, al implementar ValidationRule como una propiedad adjunta, la sintaxis se puede mejorar y puedes verla aquí