Laissez la hauteur WPF tabcontrol assume la hauteur du plus grand élément?
-
21-08-2019 - |
Question
Est-il possible d'avoir à prendre tabcontrol la taille du plus grand élément de l'onglet (bien, en fait, le contenu du TabItem)?
Depuis la tabcontrol n'a pas de taille spécifique attribué devrait autoSize:. Il le fait correctement, mais quand vous Buttées il se redimensionne automatiquement à la hauteur (et largeur) du contenu de l'onglet sélectionné
Je ne veux pas le redimensionnement se produise, et laisser le tabcontrol la hauteur assumer le poste le plus important, mais encore il s'autoSize.
Les indices? J'essayé liaison de données à la Height
propriété de chaque élément utilisé en tant que contenu à l'aide d'un MultiBinding, avec les fixations à la fois sur le ActualHeight
et les propriétés de la Items
tabcontrol. Mais hélas, le des éléments <=> de contenu est toujours 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>
...
peut-il être fait?
La solution 3
En fait, il était plus facile à résoudre que je pensais.
Depuis que j'avais un ControlTemplate pour la TabControl
de toute façon, je régler la hauteur de la présentation du contenu ContentPresenter
onglet sélectionné. Je le fais en utilisant un convertisseur qui se lie aux éléments de la Measure
, les mesures, le cas échéant (en utilisant DesiredSize
) et vérifie la taille FrameworkElement
j'ai besoin.
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;
}
Cela fonctionne très bien, avec quelques mises en garde:
- chaque contenu onglet doit être <=>
- le contenu ne change pas de taille une fois qu'ils sont chargés (parce que le convertisseur est appelé uniquement lorsque les changements de propriété des éléments, à savoir une fois).
Autres conseils
Oui il peut être fait: réutilisation grille-rowdefinitions-pour-chaque-TabItem
Exemple:
<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>
Le problème est que les TabControl
est déchargé et rechargé son contenu que vous Buttées. Par conséquent, il ne connaît que de la taille du contenu de l'onglet actif. Vous devriez être en mesure de changer la TabControl telle qu'elle jamais détruit ses enfants, et ils sont toujours présents (mais peut-être caché).
Ce blog par Eric Burke devrait vous aider à commencé. D'après ce que je peux dire par écrémage son poste, vous devrez changer de telle sorte que:
- Tous les enfants sont chargés lorsque le chargement <=>.
- Les enfants sont cachés plutôt que effondré quand ils sont inactifs
Il est sans doute pas de la bonne façon WPF, mais, si vous avez déjà tous les éléments de contenu, vous pourriez peut-être en boucle à travers eux la charge et de régler la hauteur du TabControl
programatically.
Cela a fonctionné pour moi en collaboration avec l'approche Grid.IsSharedSizeScope
ci-dessus.
Notez que SetCurrentValue
est utilisé au lieu de mettre juste la propriété SelectedIndex
- cette façon, nous gardons possibles les liaisons existantes:
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);
}