2009-11-05 24 views
3

在我的模型中,我有很多不同的對象的屬性,我檢查值,同時設置對象的值,如果該值不被接受我會拋出一個異常,這是完美的與Windows形成propertygrid,但現在我試圖設計一個使用WPF的新界面。 WPF中的 當我將屬性綁定到像文本框這樣的控件時,值被更改時我不知道如何處理異常並顯示錯誤消息。 例如:WPF DataBinding監視拋出異常

public string ConnectionString 
     { 
      get 
      { 
       return (_ConnectionString); 
      } 
      set 
      { 
       try 
       { 
        _ConnectionString = value ; 
        _SqlConnection = new System.Data.SqlClient.SqlConnection(_ConnectionString); 
        _ConnectionTested = true; 
       } 
       catch (Exception caught) 
       { 
        _ConnectionTested = false; 
        _TableNameTested = false; 
        _FieldNameTested = false; 
        _ConditionTested = false; 
        _ConnectionString = ""; 
        //----delete values---- 
        ValuesCollection.Clear(); 
        throw (new Exception("Can not Open the connection String \nReason : " + caught.Message)); 
       } 
      } 
     } 

和WPF的部分是這樣的:

<TextBox TextWrapping="Wrap" x:Name="ConnectionStringTextBox" Text="{Binding Path=ConnectionString, Mode=TwoWay}"/> 

反正是有當在文本框中的值被改變檢查,如果該模型已經引發了異常,然後顯示exception.message到用戶?

感謝

回答

3

看看binding validationBinding類有一個ValidationRules集合,您可以將其添加到ExceptionValidationRule

5

Kent對於使用ValidationRule和ExceptionValidationRule絕對正確。然而,你會發現這個解決方案非常不愉快,因爲你對這種領域有很多綁定的情況。與此

<TextBox Text="{Binding Value}" /> 

:在許多地方,你將取代像這樣

<TextBox Validation.ErrorTemplate="{StaticResource errorTemplate}"> 
    <TextBox.Text> 
    <Binding Path="Value"> 
     <Binding.ValidationRules> 
     <ExceptionValidationRule /> 
     </Binding.ValidationRules> 
    </Binding> 
    </TextBox.Text> 
</TextBox> 

因爲這是如此笨拙,我喜歡創造繼承附加屬性,自動應用驗證規則,因此所有我要說的是:

<Window 
    ValidationHelper.ErrorTemplate="{StaticResource errorTemplate}" 
... 
    <TextBox Text="{Binding Value}" /> 
    <TextBox Text="{Binding OtherValue}" /> 

我的附加屬性自動應用驗證,在窗口中的每個綁定,所以個人文本框不必擔心ABO ut驗證。

要做到這一點,我用這個一般techinique:

public class ValidationHelper : DependencyObject 
    { 
    [ThreadStatic] 
    static List<DependencyObject> _objectsNeedingValidationUpdate; 

    public static ControlTemplate GetErrorTemplate(DependencyObject obj) { return (ControlTemplate)obj.GetValue(ErrorTemplateProperty); } 
    public static void SetErrorTemplate(DependencyObject obj, ControlTemplate value) { obj.SetValue(ErrorTemplateProperty, value); } 
    public static readonly DependencyProperty ErrorTemplateProperty = DependencyProperty.RegisterAttached("ErrorTemplate", typeof(ControlTemplate), typeof(ValidationHelper), new FrameworkPropertyMetadata 
    { 
     Inherits = true, 
     PropertyChangedCallback = (obj, e) => 
     { 
      if(e.NewValue) 
      if(_objectsNeedingValidationUpdate!=null) 
       _objectsNeedingValidationUpdate.Add(obj); 
      else 
      { 
       _objectsNeedingValidationUpdate = new List<DependencyObject>(); 
       _objectsNeedingValidationUpdate.Add(obj); 
       Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new Action(UpdateValidations)); 
      } 
     }, 
    }); 

    static void UpdateValidations() 
    { 
     List<DependencyObject> objects = _objectsNeedingValidationUpdate; 
     _objectsNeedingValidationUpdate = null; 
     if(objects!=null) 
     foreach(DependencyObject obj in objects) 
      UpdateValidations(obj); 
    } 
    static void UpdateValidations(DependencyObject obj) 
    { 
     // My regular code uses obj.GetLocalValueEnumerator here, but that would require some other complexity 
     if(UpdateValidations(obj, TextBox.TextProperty)) 
     if(Validation.GetErrorTemplate(obj)==null) 
      Validation.SetErrorTemplate(obj, ValidationHelper.GetErrorTemplate(obj)); 
    } 
    static bool UpdateValidations(DependencyObject obj, DependencyProperty prop) 
    { 
     var binding = BindingOperations.GetBinding(obj, prop); 
     if(binding!=null && 
     binding.Mode==BindingMode.TwoWay && 
     !binding.ValidationRules.Any(rule => rule is ExceptionValidationRule)) 
     { 
     binding.ValidationRules.Add(new ExceptionValidationRule()); 
     BindingOperations.SetBinding(obj, prop, binding); // Required to get new rule to work 
     return true; 
     } 
     return false; 
    } 
    } 

查看驗證類的MSDN文檔中如何創建errorTemplate資源的例子。還要注意的是:

  • 我ValidationHelper類不阻止您在 個別文本框設置自定義Validation.ErrorTemplate值。這些將覆蓋ValidationHelper.ErrorTemplate。
  • 您可以輕鬆地添加比文本框其他控件和非文本
+0

你就是唯一一個誰知道如何醜陋,當一行代碼強制關進9行代碼的其他屬性的支持。 – nyconing 2017-10-31 07:09:31