2011-12-06 25 views
5

Tengo un problema con las validaciones entre múltiples campos. Por ejemplo, obtuve un ViewModel llamado RangeDateViewModel que contiene 2 instancias de una clase llamada DateViewModel, cada una de ellas representa una fecha de inicio y una fecha de finalización, respectivamente.Validación entre múltiples campos en diferentes niveles

Así que mis miradas de enlace como este -

<TextBox Text="{Binding StartDate.Date, ValidateOnDataError=True}"> 
<TextBox Text="{Binding EndDate.Date, ValidateOnDataError=True}"> 

Mi clase RangeDateViewModel implementa la interfaz IDataErrorInfo. En mi plan, el RangeDateViewModel validaría que la fecha de inicio es anterior a la fecha de finalización, mediante la aplicación de la lógica de validación en el IDataErrorInfo [ "nombrePropiedad"] función como esta -

public string this[string columnName] 
    { 
     get 
     { 
      return ValidationError(); 
     } 
    } 

El problema es que esto no es se llama, y ​​en su lugar se llaman en su lugar las propiedades IDataErrorInfo que residen en cada una de las clases de DateViewModel.

Supongo que esto se debe a que la propiedad enlazada no se encuentra en el mismo nivel de RangeDateViewModel, sino que se encuentra dentro del hijo del modelo DateViewModel.

Creo que mi necesidad es bastante básica y debe haber una solución fácil para este problema. Intenté usar ValidationRules en lugar de IDataErrorInfo, pero luego tuve problemas para que ViewModel conociera el estado de validación actual de ValidationRules.

Respuesta

1

Intente utilizar el siguiente enfoque:

  1. Crear una DataTemplate para DateViewModel:

    <DataTemplate DataType="{x:Type ViewModels:DateViewModel}"> 
        <TextBox Text="{Binding Date}"> 
    </DataTemplate> 
    
  2. Enlazar las instancias de este modelo de vista a ContentControl y establecer ValidateOnDataError a true en que la unión:

    <ContentControl Content="{Binding StartDate, ValidateOnDataError=True}" /> 
    <ContentControl Content="{Binding EndDate, ValidateOnDataError=True}" /> 
    
  3. En RangeDateViewModel suscribirse a la PropertyChanged caso de StartDate y EndDate y cuando se levanta, levanta un evento PropertyChanged con StartDate/EndDate:

    StartDate.PropertyChanged += (s, e) => InvokePropertyChanged("StartDate"); 
    EndDate.PropertyChanged += (s, e) => InvokePropertyChanged("EndDate"); 
    
+0

Gracias Daniel! Intenté lo que sugeriste, pero aparentemente aún no es lo suficientemente bueno. La propiedad IDataErrorInfo está siendo realmente accesible, pero solo en la inicialización de la plantilla, y no más tarde cuando se cambian los datos reales. Supongo que esto se debe a que StartDate y EndDate son objetos complejos que ellos mismos no están siendo cambiados, pero tienen propiedades dentro de ellos, y esto no es suficiente para elevar PropertyChanged. ¿Tal vez debería plantear un evento de alguna manera cuando cambien las propiedades de la fecha interna? – Dror

+0

@Dror: tienes razón. Vea el paso tres en la respuesta actualizada. –

+0

Gracias de nuevo Daniel! Aunque esto ha funcionado, todavía tengo un último problema menor al que me enfrento. Con esta solución, el resultado son los dos controles marcados en rojo cuando el valor no es válido. Me gustaría que en lugar de que se marquen en rojo, el Stackpanel que contiene estos dos campos se marque en "read". Preferiblemente, estos dos campos no estarán marcados, pero no es obligatorio. Intenté aplicar un DataTrigger en una propiedad bool en el RangeDateViewModel llamado "HasErrors" que establecerá "Validation.HasError" en verdadero, pero desafortunadamente es una propiedad de solo lectura. Espero que puedas ayudarme con este problema también. – Dror

1

que tenía el problema de que public string this[string columnName] simplemente no se llamaba el otro semana.

La solución fue simple. El motor de enlace de WPF vinculante no pudo seguir el anidamiento de mis modelos de vista.

Yo había asumido que necesitaba para poner en práctica la propiedad en el modelo de vista que es la corriente DataContext, pero en lugar tiene que ser implementado en el modelo de vista que es unido al control de.

Ejemplo:

<TextBox Text="{Binding Path=ProductViewModel.DescriptionViewModel.ProductName, 
            Mode=TwoWay, 
            ValidatesOnDataErrors=True, 
            NotifyOnValidationError=True}" /> 

Aquí DescriptionViewModel es la clase que contiene la propiedad unido.IDataErrorInfo necesita implementarse en esa clase (no en ProductViewModel u otra clase en la jerarquía que pueda contenerlo) entonces todo funcionará bien.

+0

Hola Sensei, gracias por tu comentario. Soy consciente de que IDataErrorInfo está funcionando bien cuando se implementa en la clase inferior en la jerarquía de enlace, pero tengo 2 problemas con ella. 1 - Obtuve dos clases involucradas en la lógica de validación pero cada una de estas clases de nivel inferior no se conocen entre sí. 2 - No quiero que solo uno de los campos se marque en rojo si el valor no es válido. Quiero que todo el control se marque en rojo. – Dror

Cuestiones relacionadas