Pergunta

Existe alguma maneira de ter a tabcontrol tomar o tamanho do maior item de guia (bem, na verdade, o conteúdo do TabItem)?

Uma vez que o tabcontrol não tem tamanho específico designado deve dimensionamento automático:. Ele faz isso corretamente, mas quando você alternar guias automaticamente redimensiona-se à altura (e largura) do conteúdo da guia selecionada no momento

Eu não quero o redimensionamento acontecer, e deixar o tabcontrol assumir a altura do maior item, mas ainda tem dimensionamento automático em si.

Qualquer pistas? Tentei ligação de dados para a propriedade Height de cada elemento usado como conteúdo ao utilizar um MultiBinding, com ligações tanto no ActualHeight e as propriedades Items do TabControl. Mas, infelizmente, o ActualHeight dos elementos de conteúdo é sempre 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>

            ...

Pode ser feito?

Foi útil?

Solução 3

Na verdade, foi mais fácil de resolver que eu pensava. Desde que eu tinha um ControlTemplate para o TabControl qualquer maneira, eu definir a altura do ContentPresenter apresentar o conteúdo guia selecionada. I fazer isso usando um conversor que se liga aos itens do TabControl, medidas los se necessário (utilizando Measure) e verifica DesiredSize para a necessidade tamanho que.

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

Isso funciona muito bem, com algumas ressalvas:

  • todos os conteúdos guia deve ser um FrameworkElement
  • o conteúdo não alterar o tamanho, uma vez que são carregados (porque o conversor só é chamado quando as mudanças de itens de propriedade, ou seja, apenas uma vez).

Outras dicas

Sim, pode ser feito: reutilização-grid-RowDefinitions-para-cada-TabItem

Exemplo:

    <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>

O problema é que as descarrega TabControl e recarrega seu conteúdo como você alternar guias. Por isso, só sabe sobre o tamanho do conteúdo na guia ativo no momento. Você deve ser capaz de mudar o TabControl tal que não destrói seus filhos, e eles estão sempre presentes (mas talvez oculto).

Este post por Eric Burke deverá fazê-lo começado. Do que eu posso dizer por desnatação seu post, você precisará alterá-lo de tal forma que:

  • Todas as crianças são carregados quando o TabControl é carregado.
  • As crianças estão escondidos em vez de colapso quando estão inativos

Provavelmente não é na forma como WPF adequada, mas, se você já tem todos os elementos de conteúdo, talvez você possa percorrer-los em carga e definir a altura do TabControl programaticamente.

Isso funcionou para mim em conjunto com abordagem Grid.IsSharedSizeScope mostrado acima.

Note que SetCurrentValue é usado em vez de apenas definir a propriedade SelectedIndex - desta forma podemos manter possíveis ligações existentes:

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);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top