2010-06-30 7 views
7

मेरे पास इसके अंदर कई अन्य नियंत्रणों के साथ एक WPF UserControl है। टेक्स्टबॉक्स इनके बीच हैं।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 = अशक्त मुझे तो मदद नहीं करेगा) इसे बदलने के लिए नहीं करना चाहती:

DataContext = _myDataContext = new MyDataContext(..); 

क्या मैं पहले से ही मिल गया है इन कक्षाओं में हैं:

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

मुझे लगता है कि इन कक्षाओं में मेरी मदद कर सकता है, लेकिन वे एक ठोस FrameworkElement की Binding की आवश्यकता होती है और मैं उन सभी के लिए विश्व स्तर पर यह करना चाहते हैं।

क्या मुझे किसी भी तरह विजुअल ट्री (जो वास्तव में मुझे पसंद नहीं है) के माध्यम से पुनरावृत्त करना चाहिए या इसके लिए कोई बेहतर समाधान है?

+0

जब आप सही मान बाँध, तो स्वचालित रूप से इसे सत्यापन त्रुटियों रीसेट कर देगा।क्या आप अपने व्यूमोडेल में INotifyPropertyChanged इंटरफ़ेस का उपयोग कर रहे हैं और संपत्ति संपत्ति बदल गई घटना को बढ़ाएगी? – Ragunathan

+0

हाँ मैं इसका उपयोग कर रहा हूं .. यही मैंने पहले किया है। लेकिन डेटासोर्स में कोई बदलाव नहीं है। इसलिए डब्ल्यूपीएफ पुराने मूल्य को –

उत्तर

2

यह एक BindingGroup के लिए ... आप सभी का एक कंटेनर पर एक BindingGroup सेट करेंगे है क्या है नियंत्रण, उदाहरण के लिए पैनल जिसमें उन्हें शामिल है। इस कारण होगा DataContext के लिए अद्यतन आयोजित होने वाले हैं जब तक आप BindingGroup पर UpdateSources कहते हैं। यदि आप उपयोगकर्ता के इनपुट रीसेट करना चाहते हैं, तो आप CancelEdit बजाय फोन चाहते हैं, और BindingGroup (अब भी नहीं बदला गया) DataContext के मूल्यों के लिए कंटेनर के अंदर सभी नियंत्रण रीसेट हो जाएंगे।

1

आप क्यों नहीं बस अपने डेटा स्रोत के सभी गुण के लिए NotifyPropertyChanged ट्रिगर नहीं करेगा? यह बाध्यकारी अद्यतन करेगा और यूआई नियंत्रण डेटाकॉन्टेक्स्ट से मूल्य प्राप्त करना चाहिए (जो वैध हैं, इस प्रकार सत्यापन त्रुटियों को मंजूरी दे दी जाएगी)?

+0

नहीं दिखाएगा .. मैंने इसे पहले की कोशिश की है .. यह काम नहीं किया: -/ –

+0

ओह, समझ गया, यह मेरे लिए काम करता है क्योंकि मैं ValidatesOnExceptions विकल्प का उपयोग करता हूं और सत्यापन अपवाद फेंक देता हूं setters। इसलिए मूल (मान्य) मान अमान्य के साथ अतिरंजित नहीं हैं। – Andrii

0

मुझे यकीन है कि आप द्वारा

मैं निर्माता में DataContext सेट क्या मतलब है नहीं कर रहा हूँ और मैं बदलने के लिए नहीं करना चाहते हैं यह (DataContext = अशक्त मुझे तो मदद नहीं करेगा)

आम तौर पर प्रपत्र आप निम्नलिखित करते पर सभी बाइंडिंग रीसेट करने के लिए: (विचारों/viewmodel तारों के लिए एक नियंत्रक संभालने, अन्यथा सिर्फ दृश्य ऑन-पीछे कोड एक का उपयोग करें।)

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; 
     } 
    } 
}