2016-10-06 74 views
-1

我正在處理一個C#/ WPF應用程序,其中有多個視圖(如A,B,C等)和相應的viewmodels.Developers將添加很多新視圖在未來的應用程序中。 每個視圖都有各種控件,如文本框,組合框,日期時間選擇器等。驗證WPF應用程序中的必填字段

我試圖想出一個必填字段的驗證方法,以便開發人員需要添加最少量的代碼來驗證新添加的視圖上的控件。

我目前的做法:

我所有的視圖模型從稱爲基類繼承「ViewModelBase」 .I've加入了這一類被稱爲IsRequiredFieldValueBlank()的新方法:

public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable 
     public bool IsRequiredFieldValueBlank(object inputObject) 
     { 
      bool isRequiredFieldValueBlank = true; 
      try 
      { 
       var arrProperties = inputObject.GetType().GetProperties(); 

       foreach (var prop in arrProperties) 
       { 
        if (!prop.CanWrite) 
         continue; 
        if(prop.PropertyType.Name.ToUpper() == "STRING") 
        {       
         if (string.IsNullOrEmpty(prop.GetValue(inputObject).ToString())) 
         { 
          isRequiredFieldValueBlank = true; 
          break; 
         } 
        } 

       } 

      } 
      catch (Exception ex) 
      { 
       //TBD:Handle exception here 
      } 
      return isRequiredFieldValueBlank; 
     } 
} 

在我查看的 「A」 XAML代碼,我有以下代碼:

<TextBox HorizontalAlignment="Left" Height="23" VerticalAlignment="Top" Width="180" TabIndex="1" Text="{Binding ProductDescription,NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource RequiredFieldStyle}" Grid.Row="1" Grid.Column="3" Margin="1,10,0,0" /> 

在我MainWindoResources.xaml

<Style TargetType="TextBox" x:Key="RequiredFieldStyle"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding Path=ViewModelBase.IsRequiredFieldValueBlank}" Value="false"> 
       <Setter Property="Background" Value="BurlyWood" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding Path=ViewModelBase.IsRequiredFieldValueBlank}" Value="true"> 
       <Setter Property="Background" Value="LightGreen" /> 
       <Setter Property="Foreground" Value="DarkGreen" /> 
      </DataTrigger>    
     </Style.Triggers> 
    </Style> 

的App.xaml:

<Application x:Class="MyTool.App" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      StartupUri="MainWindow.xaml" 
      Startup="Application_Startup"> 
    <Application.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="Views/MainWindowResources.xaml"/> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 

    </Application.Resources> 
</Application> 

我的問題:? 1.Is這種正確的做法如果是的話,那麼我理解的代碼不會工作,因爲XAML不流通inpoObject到IsRequiredFieldValueBlank ()方法在ViewModelBase類中。 有人可能會建議如何實現這一目標嗎?

2.是否有其他方法可以解決這個問題?

感謝您的幫助。

回答

0

你可以讓你的生活變得更加簡單,從長遠來看,如果你與IDataErrorInfoINotifyPropertyChanged接口充分利用Validator靜態類驗證組合。這裏是一個非常基本實現擴大對PRISM的BindableBase類:

public abstract class ViewModelBase : IDataErrorInfo, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public string Error => string.Join(Environment.NewLine, GetValidationErrors()); 

    public bool IsValid => !GetValidationErrors().Any(); 

    public string this[string columnName] => 
     GetValidationErrors().FirstOrDefault(result => result.MemberNames.Contains(columnName))?.ErrorMessage; 

    protected IEnumerable<ValidationResult> GetValidationErrors() 
    { 
     var context = new ValidationContext(this); 
     var results = new List<ValidationResult>(); 

     Validator.TryValidateObject(this, context, results, true); 

     return results; 
    } 

    protected virtual void OnPropertChanged([CallerMemberName]string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName]string propertyName = null) 
    { 
     if (Equals(storage, value)) 
     { 
      return false; 
     } 

     storage = value; 
     OnPropertChanged(propertyName); 
     return true; 
    } 
} 

你並不真的需要RequiredFieldStyle文件,然後,也是如此。驗證可以做這樣的:

public class ViewModelExample : ViewModelBase 
{ 
    private string _myString; 

    // do validation with annotations and IValidateableObject 
    [Required] 
    [StringLength(50)] 
    public string MyString 
    { 
     get { return _myString; } 
     set { SetProperty(ref _myString, value); } 
    } 
} 

只需選中IsValid屬性,看看對象是保存之前有效。