Lassen Sie WPF TabControl Höhe Höhe des größten Posten übernehmen?
-
21-08-2019 - |
Frage
Gibt es eine Möglichkeit zu haben tabcontrol die Größe des größten Registerkarte Punktes nehmen (na ja, tatsächlich, die TabItem Inhalt)?
Da die tabcontrol hat keine spezifische Größe zugewiesen sollte es autosize:. Es das tut richtig, aber wenn Sie Registerkarten wechseln Verändern der Größe sich automatisch auf die Höhe (und Breite) der Inhalt des aktuell ausgewählten Registerkarte
Ich will nicht die Redimensionierung passieren, und lassen Sie die die Höhe des größten Posten tabcontrol annehmen, aber immer noch haben sie sich autosize.
Irgendwelche Hinweise? Ich versuchte Datenbindung an die Height
Eigenschaft jedes als Inhalt verwendet Element an der einen mehrbindigen Verwendung mit Bindungen sowohl auf der ActualHeight
und den Eigenschaften des Items
tabcontrol. Aber ach, die ActualHeight
der Inhaltselemente ist immer 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>
...
Kann dies geschehen?
Lösung 3
Eigentlich war es leichter zu lösen, dass ich dachte.
Da ich sowieso einen Control für die TabControl
hatte, habe ich die Höhe des ContentPresenter
den ausgewählten Registerkarte Inhalt zu präsentieren. Ich tue dies mit einem Konverter, der auf die Elemente des TabControl
bindet, misst sie bei Bedarf (mit Measure
) und prüft DesiredSize
für die Größe ich brauche.
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;
}
Das ist ganz gut, mit einigen Einschränkungen funktioniert:
- sollte jeder Registerkarte Inhalt ein
FrameworkElement
sein - die Inhalte nicht ändern Größe, sobald sie geladen sind (weil der Konverter nur, wenn die Eigenschaft Items Änderungen, dh nur einmal aufgerufen wird).
Andere Tipps
Ja, es kann getan werden: Wiederverwendung-Grid-rowdefinitions-für-jeden-TabItem
Beispiel:
<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>
Das Problem ist, dass der TabControl
leert und lädt seinen Inhalt wie Sie Registerkarten wechseln. Daher nur er weiß um die Größe des Inhalts in den aktuell aktiven Registerkarte. Sie sollten die TabControl, so dass sie sich ändern können, nie zerstört seine Kinder, und sie sind immer vorhanden ist (aber vielleicht versteckt).
Dieser Blog-Eintrag von Eric Burke sollten Sie gestartet. Von dem, was ich durch Abschöpfen seinen Posten sagen kann, müssen Sie es ändern, so dass:
- Alle Kinder sind geladen, wenn das
TabControl
geladen wird. - Kinder sind versteckt und nicht kollabiert, wenn sie inaktiv sind
Es ist wahrscheinlich in der richtigen Art und Weise WPF nicht, aber, wenn Sie bereits alle Elemente Inhalt haben, könnten Sie vielleicht durch sie auf Lastschleife und stellen Sie die Höhe des TabControl
programmatisch.
Dies ist für mich in Verbindung mit Grid.IsSharedSizeScope
Ansatz oben gezeigt.
Beachten Sie, dass SetCurrentValue
verwendet wird, anstatt nur die SelectedIndex
-Eigenschaft - auf diese Weise wir möglich, bestehende Bindungen halten:
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);
}