2010-06-30 174 views
7

我有一個WPF UserControl與其中的許多其他控件。 TextBoxes是其中之一。 每個文本框都有自己驗證:WPF驗證:清除所有驗證錯誤

<TextBox> 
    <TextBox.Text> 
     <Binding Path="MyPath" StringFormat="{}{0:N}" NotifyOnValidationError="True"> 
      <Binding.ValidationRules> 
       <r:MyValidationRule ValidationType="decimal" /> 
      </Binding.ValidationRules> 
     </Binding> 
    <TextBox.Text> 
<TextBox> 

一個

現在假設用戶鍵入一些無效字符融入其中。他們都會變得突出紅色。

現在我想重置所有驗證錯誤(從輸入不正確),從DataContext未來設置的最近正確的價值觀

我設置的DataContext在構造函數中,我不想改變它(的DataContext = NULL不會幫我當時):

DataContext = _myDataContext = new MyDataContext(..); 

我已經發現有這些類:

Validation.ClearInvalid(..) 
BindingExpression.UpdateTarget(); 

我認爲這些課程可以幫助我,但他們需要一個具體的FrameworkElementBinding,我想對所有的人都做全球的。

我應該通過可視樹(這真的是我不喜歡)迭代或有沒有更好的解決方案呢?

+0

當您綁定正確的值時,則會自動重置驗證錯誤。你是否使用INotifyPropertyChanged接口來viewmodel&Property會引發屬性改變的事件? – Ragunathan 2010-06-30 10:28:01

+0

是的,我正在使用它..這是我第一次嘗試。但是DataSource沒有改變。因此,WPF不會反映舊值 – 2010-06-30 10:58:56

回答

2

這是一個BindingGroup是什麼?你會的所有的容器上設置BindingGroup控制,例如包含它們的面板。這會導致DataContext的更新被保留,直到您調用BindingGroup上的UpdateSources。如果你想重置用戶的輸入,你可以調用CancelEdit,而BindingGroup會將容器內的所有控件重置爲DataContext的(仍未改變的)值。

1

爲什麼不只是爲您的數據源的所有屬性觸發NotifyPropertyChanged?這將更新綁定和UI控件應該從datacontext獲取值(這是有效的,因此驗證錯誤將被清除)?

+0

不。我試過這個作爲第一..它沒有工作: -/ – 2010-07-01 06:09:36

+0

哦,明白了,它適用於我,因爲我使用ValidatesOnExceptions選項並拋出驗證異常setter方法。所以原始(有效)值不會被無效覆蓋。 – Andrii 2010-07-01 13:15:00

0

我不知道你所說的

我設置的DataContext在構造函數中的意思,我不想改變它 (的DataContext = NULL不會幫我當時)

通常以重置所有綁定你下面的形式:(假設視圖/視圖模型佈線的控制器,否則只使用一個代碼隱藏在視圖上。)

var dataContext = view.DataContext; 
view.DataContext = null; 
view.DataContext = dataContext; 

它不會將其更改爲新的數據上下文,它只會丟棄數據上下文並重新加載它。這將啓動所有綁定以重新加載。

1

我有同樣的問題。多個經過驗證的頁面上的控件。我發現,/使這個解決方案更新(和清除所有驗證)爲DependencyObject的descentents:

using System.Linq; 
using System.Windows; 
using System.Windows.Data; 
using System.Windows.Media; 

/// <summary> 
/// Updates all binding targets where the data item is of the specified type. 
/// </summary> 
/// <param name="root">The root.</param> 
/// <param name="depth">The depth.</param> 
/// <param name="dataItemType">Type of the data item.</param> 
/// <param name="clearInvalid">Clear validation errors from binding.</param> 
public static void UpdateAllBindingTargets(this DependencyObject root, int depth, Type dataItemType, bool clearInvalid) 
{ 
    var bindingExpressions = EnumerateDescendentsBindingExpressions(root, depth); 
    foreach (BindingExpression be in bindingExpressions.Where(be => be.DataItem != null && be.DataItem.GetType() == dataItemType)) 
    { 
     if (be != null) 
     { 
      be.UpdateTarget(); 
      if (clearInvalid) 
       System.Windows.Controls.Validation.ClearInvalid(be); 
     } 
    } 
} 

/// <summary> 
/// Enumerates all binding expressions on descendents. 
/// </summary> 
/// <param name="root">The root.</param> 
/// <param name="depth">The depth.</param> 
/// <returns></returns> 
public static IEnumerable<BindingExpression> EnumerateDescendentsBindingExpressions(this DependencyObject root, int depth) 
{ 
    return root.EnumerateDescendents(depth).SelectMany(obj => obj.EnumerateBindingExpressions()); 
} 

/// <summary> 
/// Enumerates the descendents of the specified root to the specified depth. 
/// </summary> 
/// <param name="root">The root.</param> 
/// <param name="depth">The depth.</param> 
public static IEnumerable<DependencyObject> EnumerateDescendents(this DependencyObject root, int depth) 
{ 
    int count = VisualTreeHelper.GetChildrenCount(root); 
    for (int i = 0; i < count; i++) 
    { 
     var child = VisualTreeHelper.GetChild(root, i); 
     yield return child; 
     if (depth > 0) 
     { 
      foreach (var descendent in EnumerateDescendents(child, --depth)) 
       yield return descendent; 
     } 
    } 
} 

/// <summary> 
/// Enumerates the binding expressions of a Dependency Object. 
/// </summary> 
/// <param name="element">The parent element.</param> 
public static IEnumerable<BindingExpression> EnumerateBindingExpressions(this DependencyObject element) 
{ 
    if (element == null) 
    { 
     throw new ArgumentNullException("element"); 
    } 

    LocalValueEnumerator lve = element.GetLocalValueEnumerator(); 

    while (lve.MoveNext()) 
    { 
     LocalValueEntry entry = lve.Current; 

     if (BindingOperations.IsDataBound(element, entry.Property)) 
     { 
      if (entry.Value is PriorityBindingExpression) 
      { 
       foreach (BindingExpression expr in ((PriorityBindingExpression)entry.Value).BindingExpressions) 
        yield return expr; 
      } 
      else if (entry.Value is MultiBindingExpression) 
      { 
       foreach (BindingExpression expr in ((MultiBindingExpression)entry.Value).BindingExpressions) 
        yield return expr; 
      } 
      else 
       yield return entry.Value as BindingExpression; 
     } 
    } 
}