2009-06-25 58 views
2

我們都知道如何開箱即用的WPF驗證。我正在嘗試一個非常簡單的事情,出於某種原因,它總是失敗。我有一個TextBox,我唯一的要求是驗證用戶在TextBox中輸入了什麼。 TextBox綁定到具有FirstName和LastName屬性的Customer對象。WPF文本框綁定驗證規則不會在LostFocus上觸發當TextBox爲空時

這裏是XAML代碼:

  <TextBox Style="{StaticResource TextBoxStyle}" Grid.Column="1" Grid.Row="0" Height="20" Width="100" Margin="10"> 
       <TextBox.Text> 
        <Binding Path="FirstName" > 
         <Binding.ValidationRules> 
          <ExceptionValidationRule /> 
         </Binding.ValidationRules> 
        </Binding> 
       </TextBox.Text> 

      </TextBox> 

這裏是Customer類姓屬性:

public string FirstName 
     { 
      get { return _firstName;} 
      set 
      { 
       if(String.IsNullOrEmpty(value)) 
        throw new ApplicationException("FirstName cannot be null or empty!"); 
       _firstName = value; 

       OnPropertyChanged("FirstName"); 
      } 
     } 

即使我拋出一個異常,如果名字(值)爲空或清空只有當我在TextBox中輸入某些內容然後將其刪除然後關閉時才能處理。原因是它依賴於財產變更事件。但即使我將該TextBox綁定到Focus上,它也不會觸發驗證。

UPDATE:

一個來處理這個問題最醜陋的方式是對的String.Empty分配給在Window.Loaded事件的文本框:

void AddCustomerWindow_Loaded(object sender, RoutedEventArgs e) 
     { 
      // get all the textboxes and set the property to empty strings! 

      txtFirstName.Text = String.Empty; 
      txtLastName.Text = String.Empty; 
     } 

這裏是綁定的代碼:

public AddCustomerWindow() 
     { 
      InitializeComponent(); 

      this.Loaded += new RoutedEventHandler(AddCustomerWindow_Loaded); 

      gvAddCustomer.DataContext = new Customer(); 
     } 

回答

0

在您的示例XAML代碼中,我看不到任何綁定。我認爲TextBox的Text屬性綁定到FirstName?

其次:首先初始化FirstName,還是返回null當被TextBox檢索?綁定到null值總是給人怪異的行爲...

試着說這在物業:

public string FirstName 
    { 
     get 
     { 
      if (_firstName == null) 
      { 
       _firstName = String.Empty; 
      } 
      return _firstName; 
     } 
     set 
     { 
      if (String.IsNullOrEmpty(value)) 
       throw new ApplicationException("FirstName cannot be null or empty!"); 
      _firstName = value; 

      OnPropertyChanged("FirstName"); 
     } 
    } 
+0

如,你可以看到更新的代碼將TextBox綁定到一個新的客戶對象。當我在TextBox和Tab中不輸入任何內容時,不會發生任何事情。它應該啓動驗證,但它不會!唯一啓動驗證的方法是在Window.Loaded事件中手動分配TextBox的.Text屬性。 – azamsharp 2009-06-26 01:15:35

0

我想你只需要指定UpdateSourceTrigger,你應該是好去(注:我通常也添加ValidatesOnDataErrors = TRUE):

0

而不必在開始設置所有的值,或使用if語句,你可以設置一個初始私有變量:

private string _FirstName = String.Empty; 
public string FirstName 
{ 
    get { return _FirstName; } 
    set 
    { 
     // Probably check for null and handle it here first 
     _FirstName = value; 
     OnPropertyChanged("FirstName"); 
    } 
} 
0

我使用的解決方案是連接控件以在失去焦點時更新自己的綁定源。這使得控件在用戶選擇或點擊一次之後驗證。

public AddCustomerWindow() 
{ 
    InitializeComponent(); 
    this.Loaded += AddCustomerWindow_Loaded; 
    gvAddCustomer.DataContext = new Customer(); 
} 

void AddCustomerWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    // Manually wire up textboxes of specific interest. 
    UpdateSourceOnLostFocus(new TextBox[] {txtFirstName, txtLastName}, 
          TextBox.TextProperty); 

    // Or, wire up ALL controls of a given type with the help of Telerik's 
    // ChildrenOfType extension, using Linq to filter the list where appropriate. 
    UpdateSourceOnLostFocus(this.ChildrenOfType<RadDatePicker>() 
           .Where(picker => !picker.IsReadOnly), 
          RadDatePicker.SelectedValueProperty); 
} 

void UpdateSourceOnLostFocus<T>(IEnumerable<T> controls, DependencyProperty prop) where T : Control 
{ 
    controls.ToList() 
     .ForEach(ctrl => 
     { 
      var binding = BindingOperations.GetBindingExpression(ctrl, prop); 
      if (binding != null) 
       ctrl.LostFocus += (sender, args) => binding.UpdateSource(); 
     }); 
} 

如果你也想在控件驗證負載 - 即用戶標籤 /通過他們點擊 - 然後你可以寫類似於上面的一個一個UpdateSourceNow方法,並從AddCustomerWindow_Loaded調用它,而不是。

但是,我更喜歡等待每個控件都被訪問,因爲當用戶想要輸入新的Model對象實例時,如果立即看到滿屏的紅色框,用戶可能會有點驚慌。

相關問題