2011-06-30 14 views
8

¿Cómo deshabilitar/habilitar un botón mientras se hace la validación usando IDataErrorInfo?Habilitar Deshabilitar el botón Guardar durante la validación usando IDataErrorInfo

Estoy usando MVVM usando GalaSoft light Framework. En mi clase de modelo he implementado IDataErrorInfo para mostrar los mensajes de error.

public string this[string columnName] 
{ 
    get 
    { 
     Result = null; 
     if (columnName == "FirstName") 
     { 
      if (String.IsNullOrEmpty(FirstName)) 
      { 
       Result = "Please enter first name"; 
      } 
     } 
     else if (columnName == "LastName") 
     { 
      if (String.IsNullOrEmpty(LastName)) 
      { 
       Result = "Please enter last name"; 
      } 
     } 

     else if (columnName == "Address") 
     { 
      if (String.IsNullOrEmpty(Address)) 
      { 
       Result = "Please enter Address"; 
      } 
     } 

     else if (columnName == "City") 
     { 
      if (String.IsNullOrEmpty(City)) 
      { 
       Result = "Please enter city"; 
      } 
     } 

     else if (columnName == "State") 
     { 
      if (State == "Select") 
      { 
       Result = "Please select state"; 
      } 
     } 

     else if (columnName == "Zip") 
     { 
      if (String.IsNullOrEmpty(Zip)) 
      { 
       Result = "Please enter zip"; 

      } 
      else if (Zip.Length < 6) 
      { 
       Result = "Zip's length has to be at least 6 digits!"; 

      } 
      else 
      { 
       bool zipNumber = Regex.IsMatch(Zip, @"^[0-9]*$"); 

       if (zipNumber == false) 
       { 
        Result = "Please enter only digits in zip"; 


       } 
      } 
     } 
     else if (columnName == "IsValid") 
     { 
      Result = true.ToString(); 
     } 

     return Result; 

    } 
} 

Captura de pantalla: http://i.stack.imgur.com/kwEI8.jpg

Cómo habilitar/deshabilitar el botón guardar. Amablemente sugerir?

Gracias

Respuesta

17

El Josh Smith Way de hacer esto es crear los métodos siguientes en el modelo:

static readonly string[] ValidatedProperties = 
{ 
    "Foo", 
    "Bar" 
}; 

/// <summary> 
/// Returns true if this object has no validation errors. 
/// </summary> 
public bool IsValid 
{ 
    get 
    { 
     foreach (string property in ValidatedProperties) 
     { 

      if (GetValidationError(property) != null) // there is an error 
       return false; 
     } 

     return true; 
    } 
} 

private string GetValidationError(string propertyName) 
{ 
    string error = null; 

    switch (propertyName) 
    { 
     case "Foo": 
      error = this.ValidateFoo(); 
      break; 

     case "Bar": 
      error = this.ValidateBar(); 
      break; 

     default: 
      error = null; 
      throw new Exception("Unexpected property being validated on Service"); 
    } 

    return error; 
} 

El modelo de vista a continuación contiene una propiedad CanSave que lee la propiedad IsValid en el modelo:

/// <summary> 
/// Checks if all parameters on the Model are valid and ready to be saved 
/// </summary> 
protected bool CanSave 
{ 
    get 
    { 
     return modelOfThisVM.IsValid; 
    } 
} 

Por último, si usted está usando RelayCommand, se puede establecer la predica te del comando a la propiedad CanSave, y la vista activará o desactivará automáticamente el botón. En el modelo de vista:

/// <summary> 
/// Saves changes Command 
/// </summary> 
public ICommand SaveCommand 
{ 
    get 
    { 
     if (_saveCommand == null) 
      _saveCommand = new RelayCommand(param => this.SaveChanges(), param => this.CanSave); 

     return _saveCommand; 
    } 
} 

Y en la vista:

<Button Content="Save" Command="{Binding Path=SaveCommand}"/> 

Y eso es todo!

PD: Si aún no ha leído el artículo de Josh Smith, cambiará su vida.

+0

que no es un buen enfoque para poner la lógica de validación en su modelo, porque la lógica de validación puede cambiar en diferentes escenarios. –

+0

Para simplificar, puede ser simplemente 'public bool IsValid => ValidatedProperties.All (p => GetValidationError (p) == null);'. – dee

8

se pueden agregar añadir un CanSave propiedad booleana y lo puso al final de su método de valiation. Enlace el IsEnabled de su botón a IsValid. algo como esto:

public bool CanSave 
{ 
    get{ return canSave; } 
    set{ canSave = value; RaisePropertyChanged("CanSave"); } 
} 
private bool canSave; 

public string this[string columnName] 
{ 
    //.... 
    CanSave = Result == String.Empty; 
} 

//xaml 
<Button IsEnabled={Binding Path=CanSave}>Save</Button> 
+0

Esto es en realidad mucho mejor que la respuesta aceptada si se utiliza 'IDataErrorInfo' si solo use los atributos de la regla de validación como estoy ahora, probablemente tenga que ir con la respuesta aceptada :) – GONeale

+5

No funciona si hay más de una validación ... this [str ing columnName] se llama por propiedad. Por lo tanto, si un prop1 no es válido y prop2 es válido, CanSave se establece en verdadero. –

+0

@PetervanKekem esa parte está en '// ....': cada vez que se llama a la función, 'Result' tiene que ser recalculada en base al resultado anterior. – stijn

1

Esta es mi manera de hacerlo usando una combinación de la interfaz IDataErrorInfo, ValidationErrors Dictionary y el sistema de mensajería MVVM-Light. Sencillo y funciona como encanto:

Modelo Clase

public Dictionary<string, string> ValidationErrors = new Dictionary<string, string>(); 

public string this[string columnName] 
{ 
    get 
    { 
    // Remove Property error from ValidationErrors prior to any validation 
    ValidationErrors.Remove(propertyName); 
    //---------------------------------------- 
    string Result = null; 
    if (columnName == "FirstName") 
    { 
     if (String.IsNullOrEmpty(FirstName)) 
     { 
      // Add Property error to ValidationErrors Dic 
      ValidationErrors[propertyName] = Result = "Please enter first name"; 
      //---------------------------------------- 
     } 
    } 
    else if (columnName == "LastName") 
    { 
     if (String.IsNullOrEmpty(LastName)) 
     { 
      // Add Property error to ValidationErrors Dic 
      ValidationErrors[propertyName] = Result = "Please enter last name"; 
      //---------------------------------------- 
     } 
    } 

    // Send MVVM-Light message and receive it in the Code Behind or VM 
    Messenger.Default.Send<PersonInfoMsg>(new PersonInfoMsg()); 
    //---------------------------------------- 
    return Result; 
    } 
} 

Ver código Detrás

public partial class PersonInfoView : UserControl 
    { 
    public PersonInfoView() 
    { 
     InitializeComponent(); 
     Messenger.Default.Register<PersonInfoMsg>(this, OnErrorMsg); 
    } 

    private void OnErrorMsg(PersonInfoMsg) 
    { 
     // In case of DataGrid validation 
     foreach (PersonInfoModel p in GridName.ItemsSource) 
     { 
      if (p.ValidationErrors.Count == 0) 
       SaveBtn.IsEnabled = true; 
      else 
       SaveBtn.IsEnabled = false; 
     } 
    } 
    } 
Cuestiones relacionadas