Microsoft-ui-xaml: Agregar soporte de validación de entrada a UWP con INotifyDataErrorInfo

Creado en 14 ene. 2019  ·  50Comentarios  ·  Fuente: microsoft/microsoft-ui-xaml

Propuesta: agregar soporte de validación de entrada con INotifyDataErrorInfo

Resumen

Agregue soporte de validación de entrada con INotifyDataErrorInfo que es compatible con x: Bind y Binding. Ambas extensiones de marcado deben obtener una nueva propiedad ValidatesOnNotifyDataErrors que sea, como en el enlace de WPF, verdadera de forma predeterminada.

Razón fundamental

Actualmente, UWP no tiene ninguna validación de entrada integrada en la plataforma. Pero cada aplicación de línea de negocio requiere validación de entrada. Es una de las características más importantes para una aplicación empresarial adecuada. Hay una entrada en uservoice que dice que esta función vendrá con WinUI, pero aún no he visto nada: https://wpdev.uservoice.com/forums/110705-universal-windows-platform/suggestions/13052589-uwp-input -validación

feature proposal needs-winui-3 team-Markup

Comentario más útil

INDEI requiere que implementes todas tus entidades y subentidades.

¿Puedes dar más detalles sobre esto?

Usando reglas, no se requieren cambios, todo funciona automáticamente usando solo atributos de validación.

En su mayor parte, todo funciona automáticamente cuando se usan ValidationAttributes y INotifyDataErrorInfo también. Mostraré algunos fragmentos de código aquí que están en la especificación, solo para que estemos (con suerte) en la misma página.

FWIW, estamos planeando tener esta clase ValidationBase en vivo en el kit de herramientas, por lo que no tiene que escribir este código repetitivo usted mismo.

public class ValidationBase : INotifyPropertyChanged, INotifyDataErrorInfo
{
   public event PropertyChangedEventHandler PropertyChanged;
   public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

   protected void SetValue<T>(ref T currentValue, T newValue, [CallerMemberName] string propertyName = "")
   {
       if (!EqualityComparer<T>.Default.Equals(currentValue, newValue))
       {
           currentValue = newValue;
           OnPropertyChanged(propertyName, newValue);
       }
   }

   readonly Dictionary<string, List<ValidationResult>> _errors = new Dictionary<string, List<ValidationResult>>();
   public bool HasErrors
   {
       get
       {
           return _errors.Any();
       }
   }
   public IEnumerable GetErrors(string propertyName)
   {
       return _errors[propertyName];
   }

   private void OnPropertyChanged(string propertyName, object value)
   {
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       Validate(propertyName, value);
   }

   private void AddErrors(string propertyName, IEnumerable<ValidationResult> results)
   {
       if (!_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors = new List<ValidationResult>();
           _errors.Add(propertyName, errors);
       }

       errors.AddRange(results);
       ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
   }

   private void ClearErrors(string propertyName)
   {
       if (_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors.Clear();
           ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
       }
   }

   public void Validate(string memberName, object value)
   {
       ClearErrors(memberName);
       List<ValidationResult> results = new List<ValidationResult>();
       bool result = Validator.TryValidateProperty(
            value,
            new ValidationContext(this, null, null)
            {
                MemberName = memberName
            },
            results
            );

        if (!result)
        {
            AddErrors(memberName, results);
        }
    }
}

Su modelo se derivaría de esa clase y se vería así:

public class Person : ValidationBase
{
    private string name;
    [MinLength(4)]
    [MaxLength(6)]
    public string Name
    {   
        get { return name; }
        set { SetValue(ref name, value); }
    }
}

Suponiendo que esta clase Person está configurada en una propiedad ViewModel en su Page , luego se vincula a eso y la validación ocurre automáticamente:

<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay}" />

Entiendo que esto puede ser un poco diferente de lo que está haciendo hoy, pero estamos tratando de no apoyar dos formas diferentes de hacer lo mismo si no es necesario. ¡Déjame saber si esto tiene sentido o si crees que todavía hay algo que nos falta!

Todos 50 comentarios

@LucasHaines , ¿cómo se relaciona esto con las funciones de validación de entrada que ha estado investigando?

@jevansaks Esto está directamente relacionado con el trabajo de validación de entrada que estoy describiendo.

Estupendo. Si tiene alguna vista previa para compartir, me complace probarlo y proporcionar comentarios e ideas.

image

Este es el tipo de validación mencionado durante Build 2018

`
x: Nombre = "Nombre de usuario" Encabezado = "Nombre de usuario:"
Text="{x:Enlazar ViewModel.Person.UserName,
UpdateSourceTrigger=PropiedadCambiada,
Modo=Dos vías}" />

x:Nombre="Contraseña" Encabezado="Contraseña:"
Contraseña = "{x: Bind ViewModel.Person.Password,
UpdateSourceTrigger=LostFocus,
Modo=Dos vías}"/>
`

@thomasclaudiushuber , ¿qué tan importante crees que es hacer que esto funcione como parte de {Binding}? Solo pregunto porque los desafíos técnicos allí no son triviales, además de que no puede funcionar a un nivel inferior. Nuestra idea original era solo admitir x: Bind, que solo requerirá cambios en el compilador de marcado y es capaz de funcionar a nivel inferior.

Además, solo planeábamos admitir el paradigma INotifyDataErrorInfo y DataAnnotations. No teníamos la intención de agregar algo análogo a Binding.ValidationRules y, por lo tanto, no sentimos que hubiera suficiente necesidad de ValidatesOnNotifyDataErrors.

¡Nos encantaría recibir sus comentarios a medida que continuamos trabajando en esta función para que se pueda hacer bien!

@stevenbrix

Respuesta corta: Sí, lo que piensas y lo que planeas suena genial. Solo x: Bind está bien, y solo INotifyDataErrorInfo también está bien.

Largo:

Solo x: ¿Enlazar? 👍

En todos los casos de WPF-LOB, puedo pensar que siempre hubo un tipo de ViewModel que se conocía en tiempo de compilación, sin tipeo de pato, por lo que x: Bind está bien. Escribí {Binding} en este número también porque pensé que podría admitirlo para obtener la misma sintaxis que en WPF. Pero esto es más "agradable de tener" que súper importante. Y como {Binding} y x:Bind son dos cosas completamente diferentes detrás de escena y el tiempo de ejecución con {Binding} no es trivial como mencionaste, olvídate de {Binding}. Creo que tenerlo solo para x: Bind está totalmente bien, funcionará para los casos de uso que se me ocurran. Y de todas las conferencias que realicé sobre UWP y x:Bind, puedo decirles que x:Bind es una de las funciones de UWP favoritas de todos los desarrolladores de XAML y les dije a todos "Prefieren x:Bind sobre Binding dondequiera que poder". :) Obtener intellisense, perf, step-into-code y errores en tiempo de compilación hace que x:Bind sea el nuevo valor predeterminado en UWP, por lo que tener el soporte de validación allí está bien y es una buena decisión, en mi opinión.

¿Solo el paradigma INotifyDataErrorInfo y DataAnnotations? 👍

Solo admitir el paradigma INotifyDataErrorInfo y DataAnnotations me parece bien. WPF no recoge las anotaciones de datos automáticamente, debe conectarlas manualmente en su implementación de INotifyDataErrorInfo mediante la clase Validator. Te refieres a esto cuando dices "paradigma de anotaciones de datos", ¿verdad? ¿O planea un soporte de anotación de datos incorporado que le permita a un desarrollador simplemente colocar una anotación de datos en una propiedad y esto simplemente funciona? ¿Como en ASP.NET Core MVC? Si bien eso sería genial, creo que no es necesario. Tener las clases ValidationContext, Validator y ValidationResult y las otras clases de System.ComponentModel.DataAnnotations es suficiente en mi opinión.

¿Agregar Binding.ValidationRules? Nooooo ;-)

No, definitivamente no agregues eso. INotifyDataErrorInfo es suficiente y es lo mejor. Creo que nunca más usé ValidationRules después de que se agregó la compatibilidad con IDataErrorInfo a WPF (si no recuerdo mal, esto fue en .NET Framework 3.5). Y cuando se agregó INotifyDataErrorInfo en .NET Framework 4.5, mis clientes y yo usamos esa interfaz en todos los proyectos para la validación de entrada. Apoyar solo esta interfaz está bien.

¿Agregar ValidateOnNotifyDataErrors? No pero...

Sí, no tienes que agregar este. Pero no tiene nada que ver con Binding.ValidationRules. Esta propiedad está directamente relacionada con la interfaz INotifyDataErrorInfo. En la extensión de marcado vinculante de WPF, ValidatesOnNotifyDataErrors es verdadero de forma predeterminada, lo que significa que {Binding} recoge la validación INotifyDataErrorInfo implementada si el objeto vinculado implementa esa interfaz. Si establece la propiedad ValidatesOnNotifyDataErrors en la extensión de marcado vinculante en falso, la extensión de marcado vinculante no seleccionará la implementación de INotifyDataErrorInfo para la validación. Entonces, tal vez esto no sea demasiado difícil de implementar con x: Bind, pero tal vez no lo necesitemos. Entonces, no, no lo hagas. Está bien dejar esto fuera. Pero permítanme describir el escenario en el que necesitaba esto en el pasado:

Los controles de WPF muestran de forma predeterminada un borde rojo que se define a través de Validation.ErrorTemplate. Ahora supongamos que tiene una implementación de INotifyDataErrorInfo con una clase que tiene la propiedad FirstName. Es obligatorio, por lo que devuelve un error si la propiedad FirstName es nula o está vacía. Ahora vinculaste un TextBox a esa propiedad FirstName. Cuando un usuario elimina ese nombre, aparece un borde rojo. Genial, exactamente lo que quieres. Pero tal vez tenga en otro lugar de la interfaz de usuario otro control que también esté vinculado a la propiedad FirstName. Por ejemplo, un TextBlock en un Tab-Header. WPF también mostrará en ese TextBlock un borde rojo cuando haya un error de validación. Pero esto podría no ser lo que quieres. Desea el error solo en el cuadro de texto donde el usuario puede cambiar el nombre, pero no en el bloque de texto en el encabezado de la pestaña. Para deshacerte del borde rojo en TextBlock, no tienes que editar el ErrorTemplate de TextBlock, sino que simplemente desactivas la validación INotifyDataErrorInfo en TextBlock-FirstName-Binding configurando la propiedad ValidatesOnNotifyDataErrors en falso. Ese es el único caso de uso que he tenido para esta propiedad. :)

Espero que esto ayude.

Resumen

Sí, estoy totalmente de acuerdo, tener validación de entrada solo en x: Bind con soporte para INotifyDataErrorInfo es un buen plan.

No, es un plan fantástico, ¡ya estoy súper emocionada!

@thomasclaudiushuber gracias por el seguimiento detallado! Los escenarios centrales que describe se alinean con lo que creemos que es el impulsor de valor real, por lo que es bueno escucharlo. El diseño general de esta característica y la API ha cambiado, principalmente debido al trabajo previo que tuvo WPF. Hubo algunas cosas importantes que mencionar aquí:

  1. Como se discutió anteriormente, hubo ciertos aspectos del sistema de validación de WPF que no sentimos que añadieran ningún valor o que fueron reemplazados por mejores patrones, por lo que no planeábamos llevarlos a UWP.

  2. Ciertas características/funcionalidad del sistema de validación de WPF aprovechan las características principales de WPF que no existen en UWP. Lo más notable aquí es la capa de adorno, que permite que cualquier UIElement en WPF muestre imágenes de validación, no solo Controles (mediante la adición de alguna parte de la plantilla).

  3. Actualmente, UWP Xaml no tiene el concepto de eventos adjuntos y, al reflejar la clase Validation, se agregaría el evento Validation.Error. No es un motivo de ruptura, solo algo para mencionar, ya que generalmente desconfiamos de agregar nuevos conceptos, ya que solo agrega complejidad. Además de eso, dado que el trabajo requiere cambios en la plantilla del control, solo el conjunto de controles para los que proporcionamos los cambios de plantilla específicos funcionaría de inmediato. En términos generales, tener una API que parece funcionar, pero no lo hace en algunos escenarios, no es una buena práctica, por lo que pensamos que sería mejor divorciarnos de ese modelo. Esto significaría tener algo más como una interfaz común y/o atributos que implementan los controles.

Todavía estamos en el proceso de entender cómo hacer revisiones de API y especificaciones en el nuevo y emocionante mundo de código abierto. Nos encantaría recibir los comentarios de la comunidad, por lo que esperamos poder publicar las propuestas de API pronto para que la comunidad pueda echar un vistazo y ayudarnos a conseguir algo que a todos les entusiasme.

@stevenbrix Cuando comience la especificación de código abierto para las funciones de validación, ¿podrá proporcionar las ilustraciones de cómo se verá la validación, así como los escenarios de muestra para que la conversación pueda ser un poco más amplia para aquellos de nosotros más en el lado de la interfaz de usuario? , que la codificación :)

@mdtauk Absolutamente. La interfaz de usuario actual que compartimos sigue siendo precisa. Si tiene comentarios, siéntase libre de proporcionarlos en este hilo.

@LucasHaines La interfaz de usuario me parece buena. Pero me pregunto cómo puede ajustar cómo se muestran los errores. No he encontrado nada al respecto y no sé si ya tienes algo para compartir en esa área. ¿Habrá algo similar a la propiedad Validation.ErrorTemplate adjunta de WPF?

¿Hay un cronograma de cuándo se publicará una propuesta/especificación formal para esto?
¿Qué puedo hacer para ayudar a que esto entre en el producto antes?

Estoy de acuerdo con @mrlacey arriba... Realmente podría usar esto ahora, así que estoy feliz de ayudar en lo que pueda.

Estamos trabajando en una especificación abierta y les haré saber a todos que está disponible en el repositorio de especificaciones.

Pregunta: ¿por qué no admitir también IDataErrorInfo? Es compatible con el estándar .net y sería extraño no admitirlo. Esto no debería afectar el rendimiento de las personas que no lo usan, ya que incluso podría verificarse en el momento de la compilación, ¿qué interfaz usar para el enlace?

Comenzamos la revisión de especificaciones abiertas para la Validación de entrada en el repositorio de especificaciones abiertas. https://github.com/Microsoft/microsoft-ui-xaml-specs/pull/26

Hola chicos, ¿cómo estamos rastreando esto? ¿Tenemos una ETA?

@knightmeister Tenemos una especificación abierta creada aquí . No dude en participar en la revisión y ayudar a dar forma a la característica. Estamos planeando enviar esto como parte de WinUI 3.0. Si desea obtener más información sobre la hoja de ruta de WinUI 3.0, consulte el número 717.

Hola a todos: echen un vistazo a las últimas muestras en la especificación. @stevenbrix realizó algunas actualizaciones excelentes en las muestras y abordó otros comentarios.

Una pregunta: ¿fluirá la información de validación a la jerarquía de control? Por ejemplo, ¿será posible que un control contenedor (p. ej., TabView o Pivot) sepa que hay un control secundario en un estado no válido?

Piense en una vista compleja con varios controles de contenedores, en la que desea resaltar qué partes de la vista requieren atención, por ejemplo, cambiando el estilo de un encabezado Pivot cuando cualquier control secundario se encuentra en un estado no válido.

Este es un tema crítico para mí.
Todo mi sistema de validación XAML se basa en las reglas de validación de WPF, lee el modelo de campo y entidad de BindingExpression y crea reglas de validación de acuerdo con los atributos de validación de DA (ver esto ).

Por ejemplo, ¿será posible que un control contenedor (p. ej., TabView o Pivot) sepa que hay un control secundario en un estado no válido?

@tbolon sí, esto es algo que se puede hacer, aunque es poco probable que haya soporte integrado en esos contenedores para ello. Pensamos en crear un control Form que tendría esta funcionalidad incorporada, pero probablemente esté pendiente en este momento. Al igual que en WPF, hay un evento ValidationError (ese nombre podría ser incorrecto) que cada control activa cuando se vuelve inválido/válido. Sin embargo, este evento no es un evento enrutado, por lo que debe suscribirse en cada elemento que le interese escuchar.

Todo mi sistema de validación XAML se basa en las reglas de validación de WPF,

@weitzhandler actualmente no planeamos agregar algo como ValidationRule a WinUI. ¿Hay algo que al usar esto te haga usar ValidationAttributes y hacer que tu modelo implemente INotifyDataErrorInfo ? Me encantaría ver cómo se ven su Modelo y XAML para comprender mejor su escenario de uso.

INDEI requiere que implementes todas tus entidades y subentidades.
Usando reglas, no se requieren cambios, todo funciona automáticamente usando solo atributos de validación.

INDEI requiere que implementes todas tus entidades y subentidades.

¿Puedes dar más detalles sobre esto?

Usando reglas, no se requieren cambios, todo funciona automáticamente usando solo atributos de validación.

En su mayor parte, todo funciona automáticamente cuando se usan ValidationAttributes y INotifyDataErrorInfo también. Mostraré algunos fragmentos de código aquí que están en la especificación, solo para que estemos (con suerte) en la misma página.

FWIW, estamos planeando tener esta clase ValidationBase en vivo en el kit de herramientas, por lo que no tiene que escribir este código repetitivo usted mismo.

public class ValidationBase : INotifyPropertyChanged, INotifyDataErrorInfo
{
   public event PropertyChangedEventHandler PropertyChanged;
   public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

   protected void SetValue<T>(ref T currentValue, T newValue, [CallerMemberName] string propertyName = "")
   {
       if (!EqualityComparer<T>.Default.Equals(currentValue, newValue))
       {
           currentValue = newValue;
           OnPropertyChanged(propertyName, newValue);
       }
   }

   readonly Dictionary<string, List<ValidationResult>> _errors = new Dictionary<string, List<ValidationResult>>();
   public bool HasErrors
   {
       get
       {
           return _errors.Any();
       }
   }
   public IEnumerable GetErrors(string propertyName)
   {
       return _errors[propertyName];
   }

   private void OnPropertyChanged(string propertyName, object value)
   {
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       Validate(propertyName, value);
   }

   private void AddErrors(string propertyName, IEnumerable<ValidationResult> results)
   {
       if (!_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors = new List<ValidationResult>();
           _errors.Add(propertyName, errors);
       }

       errors.AddRange(results);
       ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
   }

   private void ClearErrors(string propertyName)
   {
       if (_errors.TryGetValue(propertyName, out List<ValidationResult> errors))
       {
           errors.Clear();
           ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
       }
   }

   public void Validate(string memberName, object value)
   {
       ClearErrors(memberName);
       List<ValidationResult> results = new List<ValidationResult>();
       bool result = Validator.TryValidateProperty(
            value,
            new ValidationContext(this, null, null)
            {
                MemberName = memberName
            },
            results
            );

        if (!result)
        {
            AddErrors(memberName, results);
        }
    }
}

Su modelo se derivaría de esa clase y se vería así:

public class Person : ValidationBase
{
    private string name;
    [MinLength(4)]
    [MaxLength(6)]
    public string Name
    {   
        get { return name; }
        set { SetValue(ref name, value); }
    }
}

Suponiendo que esta clase Person está configurada en una propiedad ViewModel en su Page , luego se vincula a eso y la validación ocurre automáticamente:

<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay}" />

Entiendo que esto puede ser un poco diferente de lo que está haciendo hoy, pero estamos tratando de no apoyar dos formas diferentes de hacer lo mismo si no es necesario. ¡Déjame saber si esto tiene sentido o si crees que todavía hay algo que nos falta!

Tiene razón, pero eso requiere que sus entidades no sean POCO.
Debería intentarlo aunque. Puede que no sea tan malo usar una clase EntityBase en una aplicación LoB. Solo estoy acostumbrado a usar POCO.

UWP no tiene *TIENE Validación* !!!!!!! Acabo de empezar un proyecto. Volver a WPF hasta dentro de unos años.

@rufw91 Lo sé, ¿verdad?

¿Cuáles son sus limitaciones de tiempo? La primera implementación de esto está en el alfa de WinUI3, y deberíamos tener una vista previa para el escritorio de WinUI próximamente en el marco de tiempo //Build. Planeamos RTM'ing para fin de año

UWP no tiene *TIENE Validación* !!!!!!! Acabo de empezar un proyecto. Volver a WPF hasta dentro de unos años.

También he decidido seguir con WPF durante los próximos años. Lo he hecho todo (WPF, SL, WP, UWP, etc.), al final solo 1 tecnología parece sólida, que es WPF. Tal vez en unos años podría ser interesante ver dónde está WinUI, pero estoy cansado de cambiar a una nueva tecnología y quedarme solo en la oscuridad. WPF es maduro y funciona muy bien. Tal vez en unos años, Windows como sistema operativo no sea relevante en absoluto, así que esperemos eso antes de realizar más inversiones en la plataforma.

Tal vez en unos años, Windows como sistema operativo no sea relevante en absoluto, así que esperemos eso antes de realizar más inversiones en la plataforma.

Teniendo en cuenta que acabamos de superar los mil millones de instalaciones de Windows 10, me cuesta creer que eso alguna vez sea cierto. Pero definitivamente siento tu frustración y no te culpo por permanecer en WPF. FWIW, nuestro equipo se está haciendo cargo de WPF ahora, así que avíseme si hay algo que quiera que hagamos allí.

INDEI requiere que implementes todas tus entidades y subentidades.

¿Puedes dar más detalles sobre esto?

Con mi código, todas las entidades POCO pueden permanecer libres de implementar esas interfaces y permanecer sin una clase base. INPC se autoimplementa usando Fody. Lo más que haría es implementar IValidatableObject cuando se requiera una validación más refinada. Y también funciona en subtipos.

FWIW, estamos planeando tener esta clase ValidationBase en vivo en el kit de herramientas, por lo que no tiene que escribir este código repetitivo usted mismo.

Eso no es bueno. ¿Qué pasa si mis entidades ya tienen una clase base? Esa es también la razón por la que no soy tan fanático de INotifyDataErrorInfo . Las propiedades de INPC ya son un dolor de cabeza por sí mismas, especialmente cuando se trata de aplicaciones de datos masivos con toneladas de entidades.

Es bastante impactante que UWP aún no tenga la validación adecuada. Esa es una característica básica crucial en casi cualquier aplicación y se le debe dar prioridad.

Es bastante impactante que UWP aún no tenga la validación adecuada. Esa es una característica básica crucial en casi cualquier aplicación y se le debe dar prioridad.

Sí, por eso estamos trabajando en ello :)

Eso no es bueno. ¿Qué pasa si mis entidades ya tienen una clase base?

Solo estoy tratando de entender su uso aquí. ¿Cuál es la clase base y podría derivar de esta clase?

Sí, por eso estamos trabajando en ello :)

Gracias, muy agradecido. Esto y el resto de su trabajo.
¿Qué implica la etiqueta need-winui-3 ?

Solo estoy tratando de entender su uso aquí. ¿Cuál es la clase base y podría derivar de esta clase?

Estoy usando OData Connected Service para generar entidades en mi cliente.
Los objetos generados son de este patrón:

c# public abstract partial class ContactBase : Microsoft.OData.Client.BaseEntityType, INotifyPropertyChanged

¿Qué implica la etiqueta need-winui-3?

@weitzhandler
Implica que Input Validation vendrá con WinUI 3. (3.0 según lo planeado actualmente). Probablemente no llegue a WinUI 2, ya que eso requeriría cambios en el código XAML del sistema operativo, que ahora está en modo de mantenimiento.

Estoy usando UWP en una aplicación de la plataforma Uno. Esperemos que WinUI esté cubierto en su lanzamiento.
¡Gracias por la actualización!

Solo estoy tratando de entender su uso aquí. ¿Cuál es la clase base y podría derivar de esta clase?

Tener una clase base a menudo lo exige un tercero, por ejemplo, el marco de persistencia que usa. UWP/WinUI también exige una clase base solo para la validación no es una opción. Tiene que ser una interfaz para ser útil, ninguna de nuestras aplicaciones podría hacer uso de una clase base. (Eso no significa que no pueda tener una clase base para las personas que quieran usarla, solo debe ser opcional y no la única forma de realizar la validación).

Tener una clase base a menudo lo exige un tercero, por ejemplo, el marco de persistencia que usa. UWP/WinUI también exige una clase base solo para la validación no es una opción. Tiene que ser una interfaz para ser útil, ninguna de nuestras aplicaciones podría hacer uso de una clase base.

Retrocedamos un poco. Creo que los últimos comentarios que he hecho han causado un poco de confusión, que es mi culpa.

Todo lo que necesitará el modelo es implementar System.ComponentModel.INotifyDataErrorInfo (o Windows.UI.Xaml.Data.INotifyDataErrorInfo para C++). El compilador generará correctamente el código para conectarlo con su vista cuando use {x:Bind} .

La clase ValidationBase a la que me referí anteriormente es una clase de ayuda que planeábamos incluir en el kit de herramientas de la comunidad que implementa esto, junto con INotifyPropertyChanged . No hay necesidad de derivar de él si su caso de uso no lo permite.

Gracias por tu aclaración @stevenbrix.

¿Qué sucede con los atributos de validación y IValidatableObject , el tiempo de ejecución de UWP los respetará?

¿Qué hay de otros atributos, como el atributo MaxLength que mencionó anteriormente, se establecerá automáticamente una longitud máxima TextBox como en ASP.NET?
Lo mismo con DataTypeAttribute , EditableAttribute .
También DisplayAttribute para generar encabezados de campo.
Por lo que recuerdo, todos fueron compatibles con Silverlight.

(ver esto ).

¿Qué sucede con los atributos de validación y IValidatableObject? ¿Serán respetados por el tiempo de ejecución de UWP?

Así que actualmente vamos a tener soporte para el atributo Required . Algunos controles colocarán automáticamente un pequeño asterisco junto al texto del encabezado cuando se utilice. Estamos abiertos a apoyar más en el futuro si lo desea. Abra un problema separado si desea ver más, y solo para establecer expectativas, es muy poco probable que cualquier soporte de atributo adicional haga el lanzamiento inicial de WinUI3.

En cuanto a IValidatableObject , no estoy seguro de cómo funcionaría. Como generalización, nuestro motor funciona simplemente escuchando el evento INotifyDataErrorInfo.ErrorsChanged . La validación real del modelo depende del desarrollador de la aplicación y, por lo general, se realiza cuando se transfiere el valor del destino al origen.

Tal vez como un método alternativo al ValidationBase que propusiste, debería haber un conjunto de métodos de extensión que ejecuten un proceso de validación usando Validator.TryValidateObject e inyecten los resultados de la validación en la entidad, notificando los cambios. ?
De esta manera, se puede lograr fácilmente simplemente implementando INotifyDataErrorInfo . También podríamos tener una interfaz que herede de INotifyDataErrorInfo que agregue una propiedad que contenga la colección de errores, de modo que el tiempo de ejecución de UWP o el kit de herramientas pueda reconocer como una entidad validable automatizada y establecer la propiedad automáticamente si se implementa.

Tal vez como método alternativo a ValidationBase que usted propuso, debería haber un conjunto de métodos de extensión, que ejecuten un proceso de validación usando Validator.TryValidateObject, e inyecten los resultados de la validación en la entidad, notificando los cambios.

Esta es una gran idea :)

🦙 ¿Se pregunta si los nuevos paradigmas del generador de fuentes podrían ayudar aquí también?

Sí, @michael-hawker, ¡me gustan tus pensamientos!

Tuve los mismos pensamientos hace un tiempo cuando leí por primera vez sobre las posibilidades del nuevo generador de fuentes.

Creo que con los nuevos paradigmas del generador de fuentes podemos construir/generar muchas cosas entre bastidores para INotifyDataErrorInfo e INotifyPropertyChanged.

Tengo un curso de WPF en Pluralsight que hace exactamente esto con T4, INotifyPropertyChanged e INotifyDataErrorInfo, incluidas las anotaciones de datos para la validación: https://www.pluralsight.com/courses/wpf-mvvm-advanced-model-treatment
El curso también usa propiedades adjuntas personalizadas para conectar cosas.
El objetivo de este curso es mostrar cómo puede crear una aplicación MVVM WPF que muestre en cada campo de entrada si se modificó y cuál era el valor original.

Entonces, definitivamente, generar cosas y tal vez terminar con una biblioteca (tal vez como parte de WCT) sería increíble. Y me encantaría rehacer ese curso para WinUI. :)

@rufw91 Lo sé, ¿verdad?

¿Cuáles son sus limitaciones de tiempo? La primera implementación de esto está en el alfa de WinUI3, y deberíamos tener una vista previa para el escritorio de WinUI próximamente en el marco de tiempo //Build. Planeamos RTM'ing para fin de año

@stevenbrix Eso espero, tuve que volver a WPF, en realidad ya casi terminé.

Abrí este .

Para dar seguimiento a esto, después de una conversación con @stevenbrix en Twitter, integré la implementación base INotifyDataErrorInfo que proporcionó aquí en una nueva clase ObservableValidator que se incluye en el nuevo kit de herramientas MVVM (la biblioteca Microsoft.Toolkit.Mvvm ), que también implementa INotifyPropertyChanged y INotifyPropertyChanging 😄

Puede ver el código relacionado y un resumen de todo lo relacionado con esa biblioteca en este número .
También he incluido enlaces al problema original del kit de herramientas de MVVM, así como más documentos para nuevos desarrolladores.

¿Podría por favor darnos una actualización sobre esto? Es curioso si UWP 10.0 18362 es compatible con INotifyDataErrorInfo . Según la siguiente página de documentación, https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifydataerrorinfo?view=netcore-3.1 INotifyDataErrorInfo "se aplica" a UWP 10.0. Sin embargo, con UWP 10.0 18362 instalado y destinado, los cuadros de texto no muestran validaciones INotifyDataErrorInfo . Los cuadros de texto se describen en XAML de la siguiente manera:

<TextBox Text="{x:Bind ViewModel.Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

Y usamos ReactiveValidationObject como implementación INotifyDataErrorInfo aquí.

@worldbeater esto solo está disponible en las últimas vistas previas de WinUI3, ¿lo estás usando?

¡Gracias @stevenbrix! Voy a probar WinUI3. Me alegra saber que INotifyDataErrorInfo y UWP se están haciendo amigos, finalmente ✨

@worldbeater , todavía está en vista previa, ¡así que nos encantaría recibir sus comentarios al respecto! 💪

Por cierto, @worldbeater , los documentos dicen que está disponible en UWP 10.0, pero eso no significa que sea compatible con él. La documentación no es lo suficientemente clara.

¿Fue útil esta página
0 / 5 - 0 calificaciones