2012-03-28 5 views
27

मेरे पास एक टेक्स्टबॉक्स है जो एक सत्यापन नियम के साथ है जो TabControl के टैब पर है। सत्यापन त्रुटि विफल होने पर डिफ़ॉल्ट त्रुटि टेम्पलेट सही ढंग से (टेक्स्टबॉक्स के चारों ओर लाल सीमा) दिखाता है।
हालांकि यदि किसी अन्य टैब पर स्विच है और फिर टेक्स्टबॉक्स के साथ टैब पर वापस है तो त्रुटि टेम्पलेट हाइटलाइट चला गया है। यदि टेक्स्टबॉक्स में कोई परिवर्तन है तो सत्यापन नियम अभी भी बुलाया जाता है और झूठा रिटर्न देता है लेकिन त्रुटि हाइलाइट अभी भी दिखाई नहीं देता है।
केवल तभी जब टेक्स्ट सामग्री को वैध माना जाता है और फिर अमान्य होने के लिए उच्चतम वापसी होती है।
मुझे यह अच्छा लगेगा कि टेक्स्ट सामग्री अमान्य है जो किसी अन्य टैब पर स्विच कर रही है और पीछे अमान्य हाइलाइट रखती है। इस व्यवहार को पाने के लिए कोई भी विचार सबसे ज्यादा स्वागत है।
XAML: इस प्रकारसत्यापन के साथ टेक्स्टबॉक्स खो देता है टैब परिवर्तन पर त्रुटि टेम्पलेट

<TextBox Height="35" > 
    <TextBox.Text> 
    <Binding Path="pan_id" UpdateSourceTrigger="PropertyChanged"> 
     <Binding.ValidationRules> 
     <ps:PanIdValidation /> 
     </Binding.ValidationRules> 
    </Binding> 
    </TextBox.Text> 
</TextBox> 
+0

क्या आप एमवीवीएम का उपयोग कर रहे हैं? – Paparazzi

उत्तर

47

TabItem परिभाषित किया जाना चाहिए:

<TabItem Header="Foo"> 
    <Border> 
     <AdornerDecorator> 
      <Grid> 
       <TextBox Height="35" > 
        <TextBox.Text> 
         <Binding Path="pan_id" UpdateSourceTrigger="PropertyChanged"> 
          <Binding.ValidationRules> 
           <ps:PanIdValidation /> 
          </Binding.ValidationRules> 
          </Binding> 
         </TextBox.Text> 
        </TextBox> 
       </Grid> 
      </AdornerDecorator> 
     </Border> 
    </TabItem> 

मुद्दा है, Validation.Error संकेतों adorner लेयर में रंगा जाता है। जब आप टैब स्विच करते हैं, तो उस परत को त्याग दिया जाता है।

+0

बिल्कुल सही - धन्यवाद। – Ricibob

+0

कमाल! यह एक ही शैली विशेषताओं को साझा करने वाले कई नियंत्रणों को लपेटते समय भी काम करता है। – Salty

+0

इसने मुझे बहुत समय बचाया, धन्यवाद! – akagixxer

7

विशेष मामलों के लिए बस एक अतिरिक्त: मुझे इसी तरह की समस्या थी और अब मैं डायलन के कोड के समान समाधान का उपयोग कर रहा हूं।

अंतर यह है कि मेरे टैबइटेम में ग्रुपबॉक्स है और टेक्स्टबॉक्स इसके अंदर है। इस मामले में एडॉर्नर डिकोरेटर को ग्रुपबॉक्स में ही होना चाहिए, न कि टैबइटेम का प्रत्यक्ष वंशज।

तो यह काम नहीं किया:

<TabItem> 
    <AdornerDecorator> 
     <Grid> 
      <GroupBox> 
       <Grid> 
        <TextBox>...<TextBox/> 
       </Grid> 
      </GroupBox> 
     </Grid> 
    </AdornerDecorator> 
</TabItem> 

लेकिन ऐसा किया:

<TabItem> 
    <Grid> 
     <GroupBox> 
      <AdornerDecorator> 
       <Grid> 
        <TextBox>...<TextBox/> 
       </Grid> 
      </AdornerDecorator> 
     </GroupBox> 
    </Grid> 
</TabItem> 

मैं इसे द्वारा जोड़ा जा रहा है क्योंकि मैं समाधान आसानी से नहीं मिल रहा और यहां तक ​​कि AdornerLayer.GetAdornerLayer() के प्रलेखन सकता है (हालांकि सुनिश्चित नहीं है कि यह यहां लागू है) This static method traverses up the visual tree starting at the specified Visual and returns the first adorner layer found. बताता है - लेकिन शायद यह किसी बिंदु पर भी बंद हो जाता है, यह दस्तावेज़ों से स्पष्ट नहीं है।

4

जैसा कि डाइलन ने समझाया, ऐसा इसलिए है क्योंकि एडॉर्नर परत, जिसमें सत्यापन त्रुटियां खींची जाती हैं, टैब स्विच पर छोड़ दी जाती है। तो आपको सामग्री को AdornerDecorator से लपेटने की आवश्यकता है।

मैं एक व्यवहार कि TabItem की Content लपेटता एक AdornerDecorator में स्वचालित रूप से इतना है कि यह सब TabItems पर मैन्युअल रूप से किया जा करने के लिए नहीं है बनाया है।

public static class AdornerBehavior 
{ 
    public static bool GetWrapWithAdornerDecorator(TabItem tabItem) 
    { 
     return (bool)tabItem.GetValue(WrapWithAdornerDecoratorProperty); 
    } 
    public static void SetWrapWithAdornerDecorator(TabItem tabItem, bool value) 
    { 
     tabItem.SetValue(WrapWithAdornerDecoratorProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for WrapWithAdornerDecorator. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty WrapWithAdornerDecoratorProperty = 
     DependencyProperty.RegisterAttached("WrapWithAdornerDecorator", typeof(bool), typeof(AdornerBehavior), new UIPropertyMetadata(false, OnWrapWithAdornerDecoratorChanged)); 

    public static void OnWrapWithAdornerDecoratorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     var tabItem = o as TabItem; 
     if (tabItem == null) return; 

     if(e.NewValue as bool? == true) 
     { 
      if (tabItem.Content is AdornerDecorator) return; 
      var content = tabItem.Content as UIElement; 
      tabItem.Content = null; 
      tabItem.Content = new AdornerDecorator { Child = content }; 
     } 
     if(e.NewValue as bool? == false) 
     { 
      if (tabItem.Content is AdornerDecorator) 
      { 
       var decorator= tabItem.Content as AdornerDecorator; 
       var content = decorator.Child; 
       decorator.Child = null; 
       tabItem.Content = content; 
      } 
     } 
    } 
} 

आप एक डिफ़ॉल्ट शैली के माध्यम से सभी TabItems पर इस व्यवहार सेट कर सकते हैं:

<Style TargetType="TabItem"> 
    <Setter Property="b:AdornerBehavior.WrapWithAdornerDecorator" Value="True"></Setter> 
</Style> 

b नाम स्थान जहां व्यवहार स्थित है, है कुछ इस तरह (प्रत्येक परियोजना के लिए अलग होगा):

xmlns:b="clr-namespace:Styling.Behaviors;assembly=Styling" 
संबंधित मुद्दे