Prácticas recomendadas para las reglas de validación y enlace de datos de WPF

101

Tengo una aplicación WPF muy simple en la que estoy usando el enlace de datos para permitir la edición de algunos objetos CLR personalizados. Ahora quiero poner algo de validación de entrada cuando el usuario hace clic en guardar. Sin embargo, todos los libros de WPF que he leído no dedican realmente ningún espacio a este tema. Veo que puede crear reglas de validación personalizadas, pero me pregunto si esto sería excesivo para mis necesidades.

Entonces, mi pregunta es la siguiente: ¿hay una buena aplicación o artículo de muestra en algún lugar que demuestre las mejores prácticas para validar la entrada del usuario en WPF?

Mark Heath
fuente

Respuestas:

83

Creo que la nueva forma preferida podría ser usar IDataErrorInfo

Leer más aquí

Rudigrobler
fuente
3
También encontré el marco Cinch ( cinch.codeplex.com ), que incluye una demostración de la validación de las mejores prácticas en WPF + MVVM, y usa IDataErrorInfo
Mark Heath
3
En .NET 4.5 puede usar INotifyErrorInfo, que le permite devolver objetos en lugar de solo cadenas.
Peter
24

De la documentación de Patrones y Prácticas de MS :

Validación de datos e informe de errores

Su modelo de vista o modelo a menudo deberá realizar la validación de datos y señalar cualquier error de validación de datos a la vista para que el usuario pueda actuar para corregirlos.

Silverlight y WPF brindan soporte para administrar errores de validación de datos que ocurren al cambiar propiedades individuales que están vinculadas a controles en la vista. Para propiedades únicas que están vinculadas a datos a un control, el modelo de vista o el modelo puede señalar un error de validación de datos dentro del definidor de propiedades rechazando un valor incorrecto entrante y lanzando una excepción. Si la propiedad ValidatesOnExceptions en el enlace de datos es verdadera, el motor de enlace de datos en WPF y Silverlight manejará la excepción y mostrará una indicación visual al usuario de que hay un error de validación de datos.

Sin embargo, debe evitarse lanzar excepciones con propiedades de esta manera siempre que sea posible. Un enfoque alternativo es implementar las interfaces IDataErrorInfo o INotifyDataErrorInfo en su modelo de vista o clases de modelo. Estas interfaces permiten que su modelo de vista o modelo realice la validación de datos para uno o más valores de propiedad y devuelva un mensaje de error a la vista para que el usuario pueda ser notificado del error.

La documentación continúa explicando cómo implementar IDataErrorInfo e INotifyDataErrorInfo.

Palmadita
fuente
3
Me preocupé al principio cuando vi lanzar una recomendación de excepción. Me alegra ver que seguido de "lanzar excepciones con propiedades de esta manera debe evitarse siempre que sea posible"
kenwarner
22
También debe tenerse en cuenta que algunos muppet de microsoft decidieron no incluir INotifyDataErrorInfo en .net4 sino solo en silverlight. es un dolor ..
aL3891
5
@ al3891- esto se ordenará en .NET
4.5-
@ aL3891 ¿Existe alguna alternativa para el INotifyDataErrorInfo que falta?
AgentKnopf
10

Personalmente, estoy usando excepciones para manejar la validación. requiere los siguientes pasos:

  1. en su expresión de enlace de datos, debe agregar "ValidatesOnException = True"
  2. en su objeto de datos al que se vincula, debe agregar el controlador DependencyPropertyChanged donde verifica si el nuevo valor cumple con sus condiciones; de lo contrario, restaura el valor anterior del objeto (si es necesario) y lanza una excepción.
  3. en la plantilla de control que utiliza para mostrar un valor no válido en el control, puede acceder a la colección de errores y mostrar el mensaje de excepción.

el truco aquí es enlazar solo a objetos que derivan de DependencyObject. La implementación simple de INotifyPropertyChanged no funcionaría: hay un error en el marco que le impide acceder a la colección de errores.

Greg
fuente
3

Consulte también este artículo . Supuestamente, Microsoft lanzó su biblioteca empresarial (v4.0) a partir de sus patrones y prácticas donde cubren el tema de validación, pero Dios sabe por qué no incluyeron la validación para WPF, por lo que la publicación del blog a la que lo estoy dirigiendo explica lo que el autor hizo para adaptarlo. ¡Espero que esto ayude!

murki
fuente
2

Puede que le interese la aplicación de muestra BookLibrary de 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.

jbe
fuente
0

Si su clase de negocios es utilizada directamente por su interfaz de usuario, es preferible usar IDataErrorInfo porque acerca la lógica a su propietario.

Si su clase de negocio es una clase de código auxiliar creada por una referencia a un servicio WCF / XmlWeb, entonces no puede / no debe usar IDataErrorInfo ni lanzar Exception para usar con ExceptionValidationRule. En su lugar, puede:

  • Utilice ValidationRule personalizada.
  • Defina una clase parcial en su proyecto de interfaz de usuario de WPF e implemente IDataErrorInfo.
Alex Pollan
fuente
1
Sé que esto es viejo, pero espero que Alex pueda responder. Esta es la conclusión a la que también llegué, pero el problema es que tienes que escribir alguna validación para (por ejemplo) una propiedad de "Edad" que no podría ser mayor que 100 en ValidationRule, luego repetir la misma lógica en la interfaz IDataErrorInfo , que duplica la lógica. ¿Hay alguna forma de evitar eso?
JFTxJ
¿Dónde duplicas la lógica? en algún tipo de validación del servidor? Supongo que por su comentario está validando con IDataErrorInfo en la interfaz de usuario y duplicando la validación en el objeto comercial, ¿no es así? Si es así, entonces es correcto validar en ambos lados. Los objetos comerciales no pueden confiar en las UI y deben realizar su propia validación (aunque parece una duplicación)
Alex Pollan
No, la duplicación de la lógica de validación está en IDataErrorInfo y en la regla de validación personalizada ... Dado que la regla de validación personalizada es la única forma de validar los datos ANTES de que se actualicen realmente al objeto vinculado, esa validación (la edad debe ser menor luego 100) debe definirse en IDataErrorInfo para devolver un mensaje "por campo", pero también debe implementarse en la regla de validación personalizada. ¿Tiene sentido?
JFTxJ