2009-07-02 8 views
12

क्या टैबलेट को सबसे बड़ा टैब आइटम (वास्तव में, टैबिटम की सामग्री) का आकार लेने का कोई तरीका है?WPF Tabcontrol ऊंचाई सबसे बड़ी वस्तु की ऊंचाई मानने दें?

चूंकि टैबcontrol में कोई विशिष्ट आकार असाइन नहीं किया गया है, इसे ऑटोसाइज़ करना चाहिए: यह सही ढंग से करता है, लेकिन जब आप टैब स्विच करते हैं तो यह वर्तमान में चयनित टैब की सामग्री की ऊंचाई (और चौड़ाई) में स्वचालित रूप से स्वयं का आकार बदलता है।

मैं नहीं बदलना चाहता कि आकार बदलना है, और टैबcontrol को सबसे बड़ी वस्तु की ऊंचाई मानने दें, लेकिन फिर भी यह स्वयं को स्वतः बना देता है।

कोई सुराग? मैंने Height को मल्टीबाइंडिंग का उपयोग करने के लिए सामग्री के रूप में उपयोग किए जाने वाले प्रत्येक तत्व की संपत्ति को डाटाबेसिंग करने का प्रयास किया, जिसमें ActualHeight और Items दोनों टैबबैंड के गुणों के साथ बाइंडिंग के साथ। लेकिन अफसोस, सामग्री तत्वों की ActualHeight हमेशा 0.

 <TabItem Header="Core" > 
      <Grid Margin="5"> 
       <Grid.Height> 
        <MultiBinding Converter="{Converters1:AllTabContentEqualHeightConverter}"> 
         <Binding Path="ActualHeight" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}"/> 
         <Binding Path="Items" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}"/> 
        </MultiBinding> 
       </Grid.Height> 

      ... 

इस किया जा सकता है है?

उत्तर

5

असल में, मैंने सोचा कि यह हल करना आसान था। चूंकि मेरे पास TabControl के लिए नियंत्रण नियंत्रण था, इसलिए मैंने चयनित टैब सामग्री प्रस्तुत करने वाले ContentPresenter की ऊंचाई निर्धारित की है। मैं इसे कनवर्टर का उपयोग करके करता हूं जो TabControl की वस्तुओं से जुड़ा हुआ है, यदि आवश्यक हो तो उन्हें मापता है (Measure का उपयोग करके) और मुझे आवश्यक आकार के लिए DesiredSize चेक करता है।

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var items = value as ItemCollection; 

     if (items == null) 
      return null; 

     double max = 0; 
     foreach (TabItem item in items) 
     { 
      var content = item.Content as FrameworkElement; 
      if (content == null) continue; 

      if (!content.IsMeasureValid) 
       content.Measure(new Size(int.MaxValue, int.MaxValue)); 

      var height = content.DesiredSize.Height; 
      if (max < height) 
       max = height; 
     } 

     return max; 
    } 

कि बस ठीक काम करता है, कुछ कैविएट्स के साथ:

  • हर टैब सामग्री होना चाहिए एक FrameworkElement
  • सामग्री आकार में परिवर्तन नहीं करते एक बार उनके लोड कर रहे हैं (क्योंकि कनवर्टर केवल कहा जाता है जब आइटम संपत्ति बदलती है, यानी सिर्फ एक बार)।
+0

हाय @ इन्फेरिस क्या आप मुझे बता सकते हैं टैब नियंत्रण के अंदर आप टैबइटेम के संग्रह से कैसे बाध्य हैं? मुझे इसके लिए कोई जवाब नहीं मिल रहा है। – Zepee

6

समस्या यह है कि TabControl अनलोड करता है और टैब को स्विच करते समय इसकी सामग्री को फिर से लोड करता है। इसलिए यह केवल वर्तमान टैब में सामग्री के आकार के बारे में जानता है। आपको TabControl को बदलने में सक्षम होना चाहिए जैसे कि कभी भी अपने बच्चों को नष्ट कर देता है, और वे हमेशा मौजूद होते हैं (लेकिन शायद छुपाए जाते हैं)।

This blog post एरिक बर्क द्वारा आपको प्रारंभ करना चाहिए।

  • सभी बच्चों को जब TabControl भरी हुई है लोड किए गए हैं: मैं क्या अपने पद स्कीम करने से बता सकते हैं, तो आप इसे ऐसी है कि बदलने के लिए की आवश्यकता होगी।
  • बच्चे के बजाय छिपे हुए हैं ढह जब वे निष्क्रिय
+0

एक अच्छा दृष्टिकोण लगता है कि, लेकिन मैं सिर्फ यह अपने आप हल किया। फिर भी धन्यवाद। – Inferis

+0

टूटा लिंक। :( –

1

यह शायद उचित WPF रास्ते में नहीं है रहे हैं, लेकिन, अगर आप पहले से ही सभी सामग्री तत्वों है, तो आप शायद लोड पर उन के माध्यम से पाश और सेट कर सकते हैं प्रोग्रामिंग के TabControl की ऊंचाई।

+0

यह एकमात्र समाधान है जो मेरे लिए काम करता है (संयोजन के रूप में ग्रिड.इशश्रेड साइजस्कोप है) हालांकि किसी को लेआउट माप को मजबूर करने के लिए प्रोग्रामेटिक रूप से चयनित प्रत्येक टैब पर 'TabControl.UpdateLayout() 'को कॉल करना होगा। – Libor

17

हाँ, यह किया जा सकता है: reuse-grid-rowdefinitions-for-each-tabitem

उदाहरण:

<TabControl Grid.IsSharedSizeScope="True"> 
     <TabItem Header="Tab 1"> 
      <Grid > 
       <Grid.RowDefinitions> 
        <RowDefinition SharedSizeGroup="xxx"/> 
       </Grid.RowDefinitions> 
      </Grid> 
     </TabItem> 
     <TabItem Header="Tab 2"> 
      <Grid > 
       <Grid.RowDefinitions> 
        <RowDefinition SharedSizeGroup="xxx"/> 
       </Grid.RowDefinitions> 
      </Grid> 
     </TabItem> 
    </TabControl> 
+1

बस शानदार !! –

+3

कुंजी 'ग्रिड.इश शेरस्डस्कोप = "ट्रू" शामिल करने की कुंजी है, मुझे याद आया कि पहली बार - इसके बिना मेरे लिए कुछ भी नहीं बदला। यह भी ध्यान दें कि उस मान को लागू करने के लिए आपको ग्रिड के भीतर 'टैबकंट्रोल' नहीं होना चाहिए। –

+1

क्या डेटा टेम्पलेट के बावजूद इसे लागू करने का कोई तरीका है? मुझे टैबकंट्रोल मिला है अपने टैब को पॉप्युलेट करने के लिए एक संग्रह से जुड़ा हुआ है। मैंने बिना किसी सफलता के सभी टैबों में चौड़ाई/ऊंचाई साझा करने के लिए पंक्ति और कॉलम परिभाषाओं को सेट करने का प्रयास किया है (मैं ग्रिड.इशश्रेड साइजस्कोप = "ट्रू" टैबकंट्रोल पर सेट करता हूं) – Zepee

0

यह Grid.IsSharedSizeScope दृष्टिकोण के साथ संयोजन के रूप में मेरे लिए काम किया ऊपर दिखाए गए।

ध्यान दें कि SetCurrentValue सिर्फ SelectedIndex संपत्ति निर्धारित करने के बजाय प्रयोग किया जाता है - इस तरह से हम संभव मौजूदा बाइंडिंग रखें:

private void TabControl_OnLoaded(object sender, RoutedEventArgs e) 
{ 
    //NOTE: loop through tab items to force measurement and size the tab control to the largest tab 
    TabControl tabControl = (TabControl)sender; 

    // backup selection 
    int indexItemLast = tabControl.SelectedIndex; 

    int itemCount = tabControl.Items.Count; 

    for (
     int indexItem = (itemCount - 1); 
     indexItem >= 0; 
     indexItem--) 
    { 
     tabControl.SetCurrentValue(Selector.SelectedIndexProperty, indexItem); 
     tabControl.UpdateLayout(); 
    } 

    // restore selection 
    tabControl.SetCurrentValue(Selector.SelectedIndexProperty, indexItemLast); 
}