2009-07-02 55 views
12

有什麼辦法可以讓tabcontrol獲取最大標籤項目的大小(實際上,tabitem的內容)?讓WPF Tabcontrol高度假定最大物品的高度?

由於tabcontrol沒有指定特定的大小,它應該自動調整大小:它可以正確地做到這一點,但是當切換選項卡時,它會自動將其自身調整爲當前選定選項卡內容的高度(和寬度)。

我不想調整大小,讓tabcontrol承擔最大項目的高度,但仍然讓它自動自動調整大小。

任何線索?我嘗試使用數據綁定到每個元素的Height屬性作爲使用多重綁定的內容,同時綁定在Tabcontrol的ActualHeightItems兩個屬性上。但唉,內容元素的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
  • 一旦被加載的內容不會改變大小(因爲轉換器只調用當Items屬性發生變化時,即只有一次)。
+0

您好@Inferis能告訴我如何綁定到Tab控件的TabItem集合?我似乎無法找到答案。 – Zepee 2015-07-03 15:45:49

6

問題是TabControl在切換標籤頁時會卸載並重新加載其內容。因此它只知道當前活動選項卡中內容的大小。您應該能夠更改TabControl,使其不會破壞其子項,並且它們始終存在(但可能隱藏)。

This blog post Eric Burke應該讓你開始。我可以通過瀏覽他的帖子來看出,你需要改變它:

  • 所有的孩子在加載TabControl時加載。
  • 兒童被隱藏,而不是崩潰了,當他們處於非活動狀態
+0

這似乎是一個好辦法,但我只是解決了它自己。不管怎麼說,還是要謝謝你。 – Inferis 2009-07-02 13:24:46

+0

斷開的鏈接。 :( – 2016-01-10 19:21:35

1

它可能不是在正確的WPF的方式,但是,如果你已經有了所有的內容元素,你可以通過它們的負載可能循環,並設置編程的高度TabControl

+0

這是我工作的唯一解決方案(聯合使用Grid.IsSharedSizeScope),但必須在每個以編程方式選擇的選項卡上調用`TabControl.UpdateLayout()`以強制進行佈局測量。 – Libor 2017-08-22 22:59:21

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