15

有没有办法让 tabcontrol 获取最大选项卡项的大小(实际上,是 tabitem 的内容)?

由于 tabcontrol 没有分配特定的大小,它应该自动调整大小:它正确地做到了,但是当您切换选项卡时,它会自动将自身调整为当前选定选项卡内容的高度(和宽度)。

我不希望发生调整大小,并让 tabcontrol 假设最大项目的高度,但仍然让它自动调整大小。

有什么线索吗?我尝试对Height用作内容的每个元素的属性进行数据绑定,以使用多重绑定,并绑定 TabcontrolActualHeight的属性和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>

            ...

这可以做到吗?

4

5 回答 5

27

是的,可以做到: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>
于 2013-02-07T05:48:08.900 回答
7

问题是TabControl当您切换标签时卸载并重新加载其内容。因此它只知道当前活动选项卡中内容的大小。您应该能够更改 TabControl,使其永远不会破坏其子级,并且它们始终存在(但可能隐藏)。

Eric Burke 的这篇博文应该可以帮助您入门。从我通过浏览他的帖子可以看出,您需要对其进行更改,以便:

  • 加载时加载所有子TabControl项。
  • 子项在不活动时被隐藏而不是折叠
于 2009-07-02T11:42:14.163 回答
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 属性更改时调用,即仅调用一次)。
于 2009-07-02T13:29:58.907 回答
3

这与上面显示的方法一起对我有用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);
}
于 2017-08-22T23:05:56.793 回答
1

它可能不是正确的 WPF 方式,但是,如果您已经拥有所有内容元素,您可以在加载时循环它们并以TabControl编程方式设置高度。

于 2009-07-02T11:54:33.780 回答