2011-07-06 107 views
3

我與DataGrid的一個簡單的WPF應用程序wchich被綁定到該列表以Employee對象:WPF Datagrid的新行驗證

public class Employee 
{ 
    private string _name; 

    public int Id { get; set; } 


    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      if (String.IsNullOrEmpty(value)) 
       throw new ApplicationException("Name cannot be empty. Please specify the name."); 
      _name = value; 
     } 
    } 

正如你所看到的,我想阻止不設置Name屬性創建員工。 所以,我做了一個驗證規則:

public class StringValidationRule : ValidationRule 
{ 
    public override ValidationResult Validate(object value, CultureInfo cultureInfo) 
    { 
     string str = value as string; 
     if (String.IsNullOrEmpty(str)) 
      return new ValidationResult(false, "This field cannot be empty"); 
     else 
      return new ValidationResult(true, null); 
    } 
} 

的名稱字段的XAML如下:

<DataGridTextColumn Header="Name" 
           ElementStyle="{StaticResource datagridElStyle}" > 
       <DataGridTextColumn.Binding> 
        <Binding Path="Name" Mode="TwoWay" NotifyOnValidationError="True" ValidatesOnExceptions="True" UpdateSourceTrigger="PropertyChanged" > 
         <Binding.ValidationRules> 
          <emp:StringValidationRule/> 
         </Binding.ValidationRules> 
        </Binding> 
       </DataGridTextColumn.Binding> 
      </DataGridTextColumn> 

如果我嘗試編輯在DataGrid中現有員工行的名稱,將其設置爲空字符串,datagrid標記錯誤的字段,不允許保存行。這是正確的行爲。

但是,如果我創建一個新行並在鍵盤上按回車鍵,這個新行創建_name設置爲NULL,驗證不起作用。我想這是因爲DataGrid調用新行對象的默認構造函數並將_name字段設置爲NULL。

什麼是驗證新行的正確方法?

回答

2

您可以在Employee對象上實施IDataError。這here有一個很好的網頁。

+0

謝謝,我會研究它,並張貼在這裏,如果我找到任何解決方案。但驗證編輯工作正常,我認爲可能有一些簡單的方法來驗證新行,因爲這是一項非常普遍的任務。 – MyUserName

+0

是的,Employee類中的IDataError實現有所幫助。我在這裏找到了一個很好的例子:http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx#errorinfo – MyUserName

+0

@MyUserName:很高興幫助。 :) –

0

我實際上遇到了同樣的問題,但是因爲我一直在使用MVC數據註釋,如Karl Shifflett所示:http://bit.ly/18NCpJU。我最初認爲這是一個好主意,但我現在意識到,微軟不打算包含MVC數據註釋,因爲這些註釋似乎更適合提交表單,但不是數據持續存在並且可以編輯的應用程序會議,但我離題..

這是我做臨時解決方法。長期的解決方案將實施IDataError:

// BusinessEntityBase is what allows us to 
// use MVC Data Annotations (http://bit.ly/18NCpJU) 
public class MyModel : BusinessEntityBase 
{ 
    private string _name; 
    private List<Action> _validationQueue = new List<Action>(); 
    private Timer _timer = new Timer { Interval = 500 }; 

    [Required(AllowEmptyStrings = false)] 
    public string Name 
    { 
     get 
     { 
      return this._name; 
     } 
     set 
     { 
      var currentValue = this._name; 
      this._name = value; 
      base.RaisePropertyChanged("Name"); 

      this.AddValidationAction("Name", currentValue, value ); 
     } 
    } 

    private void AddValidationAction<T>(string Name, T currentValue, T newValue) 
    { 
     Action validationAction = 
      () => 
       base.SetPropertyValue(Name, ref currentValue, newValue); 
     _validationQueue.Add(validationAction); 
     this._timer.Enabled = true; 
    } 

    private void ProcessValidationQueue(object sender, ElapsedEventArgs e) 
    { 
     if(_validationQueue.Count > 0) 
     { 
      while (_validationQueue.Count > 0) 
      { 
       _validationQueue[0].Invoke(); 
       _validationQueue.RemoveAt(0); 
      } 
     } 

     this._timer.Enabled = false; 
    } 

    public MyModel() 
    { 
     _timer.Enabled = false; 
     _timer.Elapsed += this.ProcessValidationQueue; 
     _timer.Start(); 
    } 
}