Пусть высота WPF Tabcontrol предполагает высоту самого большого элемента?

StackOverflow https://stackoverflow.com/questions/1073770

Вопрос

Есть ли какой-нибудь способ заставить tabcontrol принимать размер самого большого элемента вкладки (ну, на самом деле, содержимого tabitem)?

Поскольку tabcontrol не имеет назначенного определенного размера, он должен автоматически изменять размер:он делает это правильно, но при переключении вкладок он автоматически изменяет размер до высоты (и ширины) содержимого текущей выбранной вкладки.

Я не хочу, чтобы происходило изменение размера, и пусть tabcontrol принимает высоту самого большого элемента, но все равно автоматически изменяет его размер.

Есть какие-нибудь зацепки?Я попробовал привязку данных к Height свойство каждого элемента, используемого в качестве содержимого для использования мультисвязывания, с привязками как к ActualHeight и тот Items свойства Tabcontrol.Но, увы, 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>

            ...

Можно ли это сделать?

Это было полезно?

Решение 3

На самом деле, решить эту проблему было проще, чем я думал.Поскольку у меня был controltemplate для 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, т. Е. только один раз).

Другие советы

Да, это можно сделать: повторное использование-grid-rowdefinitions-для-каждого-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>

Проблема в том, что TabControl выгружает и перезагружает его содержимое при переключении вкладок.Поэтому он знает только о размере содержимого на текущей активной вкладке.Вы должны быть в состоянии изменить TabControl таким образом, чтобы он никогда уничтожает своих детей, а они всегда присутствуют (но, возможно, скрыты).

Это сообщение в блоге автор: Эрик Берк, это должно помочь вам начать.Из того, что я могу сказать, просмотрев его пост, вам нужно будет изменить его таким образом, чтобы:

  • Все дочерние элементы загружаются, когда TabControl загружено.
  • Дочерние элементы скрыты, а не свернуты, когда они неактивны

Вероятно, это неправильно в формате WPF, но, если у вас уже есть все элементы содержимого, возможно, вы могли бы перебирать их при загрузке и устанавливать высоту TabControl программно.

Это сработало для меня в сочетании с 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);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top