2011-06-30 26 views
8

Jak wyłączyć/włączyć przycisk podczas sprawdzania poprawności za pomocą IDataErrorInfo?Włącz Wyłącz przycisk zapisywania podczas sprawdzania poprawności za pomocą IDataErrorInfo

Używam MVVM przy użyciu GalaSoft light Framework. W mojej klasie modelu zaimplementowałem IDataErrorInfo, aby wyświetlić komunikaty o błędach.

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; 

    } 
} 

Zrzut ekranu: http://i.stack.imgur.com/kwEI8.jpg

Jak wyłączyć/włączyć przycisk Zapisz. Uprzejmie sugerujesz?

Dzięki

Odpowiedz

17

Josh Smith Way to zrobić jest stworzenie jednej z następujących metod w modelu:

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; 
} 

ViewModel następnie zawiera CanSave obiekt, który odczytuje właściwość IsValid od modelu:

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

Wreszcie, jeśli używasz RelayCommand można ustawić Predica te polecenie do właściwości CanSave, a widok automatycznie włączy lub wyłączy przycisk. W ViewModel:

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

     return _saveCommand; 
    } 
} 

I w Widoku:

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

I to jest to!

PS: Jeśli jeszcze nie czytałeś artykułu Josha Smitha, zmieni to twoje życie.

+0

To nie jest dobre podejście do umieszczenia logiki walidacyjnej w modelu, ponieważ logika walidacji może się zmienić w innym scenariuszu. –

+0

Dla uproszczenia może to być po prostu 'public bool IsValid => ValidatedProperties.All (p => GetValidationError (p) == null);'. – dee

8

można dodać dodać logiczną właściwość CanSave i ustawić go na końcu swojej metodzie valiation. Zwiąż IsEnabled z przycisku do IsValid. Somthing tak:

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

To jest rzeczywiście znacznie lepiej niż przyjętym odpowiedź, jeśli używasz 'IDataErrorInfo' jeśli ciebie po prostu używaj atrybutów reguł sprawdzania poprawności, tak jak teraz, prawdopodobnie musisz iść z zaakceptowaną odpowiedzią :) – GONeale

+5

Nie działa, jeśli istnieje więcej niż jedna weryfikacja ... to [str ing columnName] jest wywoływana dla każdej właściwości. Więc jeśli prop1 jest nieważny, a prop2 jest poprawny, CanSave jest ustawione na true. –

+0

@PetervanKekem część jest w '// ....': za każdym razem, gdy funkcja jest wywoływana, 'Wynik' musi zostać ponownie obliczony na podstawie poprzedniego wyniku. – stijn

1

Oto mój sposób robienia tego za pomocą kombinacji interfejsu IDataErrorInfo, ValidationErrors Dictionary i systemu komunikatów MVVM-Light. Prosta i działa jak czar:

model Class

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; 
    } 
} 

View Code Behind

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; 
     } 
    } 
    } 
Powiązane problemy