2010-03-26 10 views
10

समस्या
मैं क्रोम के आकार टैब कि एक ViewModel को बांधता है का उपयोग कर एक कस्टम टैब नियंत्रण है। आकार के कारण, किनारों थोड़ा ओवरलैप। मेरे पास एक ऐसा फ़ंक्शन है जो टैब Item के ZIndex को TabControl_SelectionChanged पर सेट करता है जो टैब का चयन करने और टैब को खींचने/छोड़ने के लिए ठीक काम करता है, हालांकि जब मैं रिले कमांड के माध्यम से एक टैब जोड़ता या बंद करता हूं तो मुझे असामान्य परिणाम मिल रहे हैं। क्या किसी के पास कोई विचार है?WPF - ओवरलैपिंग एक TabControl में कस्टम टैब और zindex

डिफ़ॉल्ट दृश्य:

निकाला जा रहा है टैब:

एक पंक्ति में 2 या अधिक टैब जोड़ना:

एक समय में 1 टैब जोड़ना और हाल ही में जोड़े गए टैब के ज़िन्डेक्स को रीसेट नहीं करेगा, इसलिए वे दाईं ओर वाले टैब के पीछे जाते हैं, और टैब बंद करने से चयनित टैब के ZIndex को सही ढंग से प्रस्तुत नहीं किया जाता है और यह इसके पीछे दिखाई देता है अपने दाहिनी ओर टैब।

कोड zindex

private void PrimaryTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (e.Source is TabControl) 
     { 
      TabControl tabControl = sender as TabControl; 
      ItemContainerGenerator icg = tabControl.ItemContainerGenerator; 
      if (icg.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) 
      { 
       foreach (object o in tabControl.Items) 
       { 
        UIElement tabItem = icg.ContainerFromItem(o) as UIElement; 
        Panel.SetZIndex(tabItem, (o == tabControl.SelectedItem ? 100 : 
         90 - tabControl.Items.IndexOf(o))); 
       } 
      } 
     } 
    } 

स्थापित करने के लिए breakpoints का उपयोग कर रहा है कि इसे सही ढंग से मैं इसे करने के लिए, लेकिन लेआउट परिवर्तन दिखाई नहीं दे रहा क्या चाहते करने के लिए zindex स्थापित कर रही है देख सकते हैं। मुझे पता है कि कुछ बदलाव प्रभावी हैं क्योंकि यदि उनमें से कोई भी काम नहीं कर रहा था तो टैब किनारों को उलट दिया जाएगा (दाएं टैब बाईं ओर के ऊपर खींचे जाएंगे)। किसी टैब पर क्लिक करने से सभी टैबों के ज़िन्डेक्स को सही ढंग से सेट किया जाएगा (जिसमें शीर्ष पर खींचा जाना चाहिए) और उन्हें पुनर्व्यवस्थित करने के लिए उन्हें ड्रैग/ड्रॉप करना भी सही ढंग से प्रस्तुत करता है (जो टैब आइटम को हटा देता है और फिर से जोड़ता है)। एकमात्र अंतर जो मैं सोच सकता हूं वह है कि मैं एमवीवीएम डिज़ाइन पैटर्न का उपयोग कर रहा हूं और बटन जो ऐड/बंद टैब रिले कमांड हैं।

क्या किसी को पता है कि यह क्यों हो रहा है और मैं इसे कैसे ठीक कर सकता हूं ??

पेज। मैंने अपने व्यूमोडेल में ज़िन्डेक्स सेट करने और इसके लिए बाध्यकारी करने का प्रयास किया, हालांकि रिले कमांड के माध्यम से टैब जोड़ने/हटाने के दौरान भी वही होता है।

+0

अब मुझे लगता है कि यह WPF के साथ एक मुद्दा है और मेरा कोड नहीं है। मैंने एक बटन जोड़ा जो टैब आइटम के ज़िन्डेक्स को खींचा जाने के बाद प्रदर्शित करता है और ज़िन्डेक्स उन सभी पर निश्चित रूप से सही है, वे ठीक से नहीं खींचे जा रहे हैं। – Rachel

+0

हाय वहाँ। एक टैबकंट्रोल में टैब को क्रोम-जैसे ट्रैपेज़ॉयडल आकार में देना और उन्हें सही तरीके से व्यवहार करने के लिए वास्तव में डब्ल्यूपीएफ में काफी मुश्किल लगती है। आप जिस एक्सएएमएल को टेम्पलेटिंग/स्टाइलिंग के लिए इस्तेमाल करते हैं, उसे साझा करने का कोई मौका? मेरे यहां एक समाधान है, लेकिन यह विशेष रूप से सुरुचिपूर्ण नहीं है - जो आपने किया है उत्सुक है! चीयर्स। – Noldorin

+0

निश्चित रूप से, कोड यहां पोस्ट करने के लिए बहुत लंबा है लेकिन मैं इसे समझाने की कोशिश करूंगा। यदि आपके पास प्रश्न हैं तो मुझे [email protected] पर ईमेल करने के लिए स्वतंत्र महसूस करें। प्रत्येक टैब वास्तव में 3 कोशिकाओं के साथ एक ग्रिड होता है - बाएं और दाएं वाले में एक पथ होता है जो वक्र खींचता है और मध्य में डेटा होता है। प्रत्येक ग्रिड में नकारात्मक मार्जिन सेट होता है ताकि उन्हें ओवरलैप कर दिया जा सके, और ज़िन्डेक्स का उपयोग यह निर्धारित करने के लिए किया जाता है कि कौन सा शीर्ष पर होना चाहिए। सुनिश्चित नहीं है कि आप ड्रैग/ड्रॉप या स्क्रॉलिंग जोड़ रहे हैं, लेकिन मेरे मामले में सभी टैब स्क्रॉलिंग के लिए स्क्रॉलव्यूअर में निहित हैं और ड्रैगड्रॉप टैबकंट्रोल के आइटम्स कंट्रोल के लिए एक संलग्न प्रॉपर्टी है। – Rachel

उत्तर

5

धन्यवाद एबे, आपकी दूसरी टिप्पणी मुझे मेरे समाधान में ले जाती है!

मैंने लूप के प्रत्येक पुनरावृत्ति के लिए tabItem.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate); जोड़ा।

मुझे अभी भी सीखने में दिलचस्पी होगी कि अगर किसी और को प्रत्येक टैब पर रीफ्रेश किए बिना इस पर एक रास्ता मिल जाए तो प्रत्येक बदलाव पर। मैंने लूप के अंत में पूरे टैब नियंत्रण को रीफ्रेश करने का प्रयास किया लेकिन वह केवल टैब को बंद करने के लिए काम करता था, उन्हें जोड़ नहीं रहा था। मुझे पता है कि पैनल.जेंडेक्स सही ढंग से सेट हो रहा है, यह प्रतिपादन करते समय उस संपत्ति का सम्मान नहीं कर रहा है।

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

private void PrimaryTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (e.Source is TabControl) 
     { 
      TabControl tabControl = sender as TabControl; 

      tabControl.Dispatcher.BeginInvoke(
       new Action(() => UpdateZIndex(sender as TabControl)), 
       DispatcherPriority.Background); 
     } 
    } 

    private void UpdateZIndex(TabControl tabControl) 
    { 
     ItemContainerGenerator icg = tabControl.ItemContainerGenerator; 

     if (icg.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated) 
     { 
      foreach (object o in tabControl.Items) 
      { 
       UIElement tabItem = icg.ContainerFromItem(o) as UIElement; 
       if (tabItem != null) 
       { 
        // Set ZIndex 
        Panel.SetZIndex(tabItem, (o == tabControl.SelectedItem ? 100 : 
         90 - tabControl.Items.IndexOf(o))); 
       } 
      } 
     } 
    } 
+1

.NET 4.0 में अपग्रेड करने से भी समस्या ठीक हो गई – Rachel

1

ऐसा लगता है कि संग्रह में परिवर्तन होने पर आपको अपने एल्गोरिदम को फिर से चलाने की आवश्यकता है। चूंकि आप ItemContainerGenerator.Status संपत्ति का परीक्षण कर रहे हैं, इसलिए एल्गोरिदम नहीं चल सकता है। आप StatusChanged ईवेंट को सुनना चाह सकते हैं, और जब यह ContainersGenerated में बदल जाता है तो फिर एल्गोरिदम चलाता है।

+0

मैंने यह कोशिश की है और यह अभी भी सही तरीके से दिखाई नहीं दे रहा है। साथ ही, ItemContainerGenerator.StatusChanged ईवेंट चयनित इटैम अपडेट होने से पहले चलता है ताकि सेटिंग हमेशा चयनित टैब को अंतिम-चयनित टैब पर सेट कर दे। ब्रेकपॉइंट्स का उपयोग करके मैं देख सकता हूं कि TabControl_SelectionChanged ईवेंट का उपयोग करके टैब को जोड़/हटाते समय पैनल.जेंडेक्स निश्चित रूप से सही ढंग से सेट हो रहा है, हालांकि यह उन्हें जिस तरह से करना चाहिए उसे आकर्षित नहीं करता है। मेरे लिए यह समझ में नहीं आता है क्योंकि ड्रैग/ड्रॉइंग टैब (जो टैबआईटम को भी हटा देता है और दोबारा जोड़ता है) टैब ऑर्डर सही तरीके से खींचता है। – Rachel

+2

हाँ, यह अजीब है। डीएंडडी के बीच एकमात्र अंतर मैं सोच सकता हूं और केवल एक नया आइटम जोड़ना ज़ेड-इंडेक्स एल्गोरिदम चलाए जाने का समय होगा। शायद इसे कम प्राथमिकता पर डिस्पैचर पर आवेदक (जैसे DispatcherPriority.Input) पर एक (हैकी) समाधान होगा। –

संबंधित मुद्दे