Lasciate che WPF Tabcontrol altezza assumere altezza di voce più importante?
-
21-08-2019 - |
Domanda
C'è un modo per avere a tabcontrol prendere la dimensione del più grande voce di scheda (beh, in realtà, il tabitem contenuto)?
Dal momento che il controllo tabcontrol non ha dimensioni specifiche assegnate dovrebbe autosize:lo fa correttamente, ma quando si passa schede si ridimensiona automaticamente all'altezza (larghezza) il contenuto della scheda attualmente selezionata.
Non voglio che il ridimensionamento per accadere, e lasciare che il controllo tabcontrol assumere l'altezza della voce più importante, ma ancora autosize stesso.
Eventuali indizi?Ho provato il databinding per il Height
la struttura di ogni elemento usato come contenuto per l'utilizzo di un multibinding, con associazioni su entrambi i ActualHeight
e il Items
proprietà del controllo Tabcontrol.Ma, ahimè, il ActualHeight
di elementi di contenuto, è 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>
...
Questo può essere fatto?
Soluzione 3
In realtà, era più facile da risolvere che ho pensato.Da quando ho avuto un controltemplate per il TabControl
comunque, ho impostato l'altezza del ContentPresenter
presentando la scheda selezionata contenuto.Eseguire questa operazione utilizzando un convertitore che si lega agli elementi di TabControl
, misure se necessario (utilizzando Measure
) e controlli DesiredSize
per le dimensioni di cui ho bisogno.
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;
}
Che funziona bene, con alcune avvertenze:
- ogni scheda contenuto dovrebbe essere un
FrameworkElement
- i contenuti non cambiano di dimensione, una volta caricato (perché il convertitore viene chiamato solo quando gli Elementi variazioni di proprietà, ovvero solo una volta).
Altri suggerimenti
Sì, si può essere fatto: riuso-griglia-rowdefinitions-per-ogni-tabitem
Esempio:
<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>
Il problema è che il TabControl
scarica e ricarica il suo contenuto, come si cambia schede.Pertanto, si conosce solo la dimensione del contenuto in attivo tab.Si dovrebbe essere in grado di cambiare il TabControl tale che mai distrugge i suoi figli, e sono sempre presente (ma forse nascosto).
Questo post del blog da Eric Burke dovrebbe iniziare.Da quello che posso dire scrematura il suo post, è necessario modificare tale che:
- Tutti i bambini vengono caricati quando il
TabControl
viene caricato. - I bambini sono nascosti piuttosto che crollò quando sono inattivi
Probabilmente non è corretto WPF modo, ma, se si dispone già di tutti gli elementi di contenuto, si potrebbe forse loop attraverso di loro sul carico e impostare l'altezza del TabControl
a livello di programmazione.
Questo ha funzionato per me in collaborazione con Grid.IsSharedSizeScope
approccio indicato sopra.
Nota che SetCurrentValue
è utilizzato invece di solo il SelectedIndex
la struttura, in questo modo manteniamo possibile esistenti associazioni:
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);
}