Is there any way to have to tabcontrol take the size of the largest tab item (well, actually, the tabitem\'s content)?
Since the tabcontrol has no specific size assi
Yes it can be done: reuse-grid-rowdefinitions-for-each-tabitem
Example:
<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>
Actually, it was easier to solve that I thought.
Since I had a controltemplate for the TabControl
anyway, I set the height of the ContentPresenter
presenting the selected tab content. I do this using a converter that binds to the items of the TabControl
, measures them if necessary (using Measure
) and checks DesiredSize
for the size I need.
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;
}
That works just fine, with some caveats:
FrameworkElement
The problem is that the TabControl
unloads and reloads its content as you switch tabs. Therefore it only knows about the size of the content in the currently active tab. You should be able to change the TabControl such that it never destroys its children, and they are always present (but maybe hidden).
This blog post by Eric Burke should get you started. From what I can tell by skimming his post, you will need to change it such that:
TabControl
is loaded.It's probably not in the proper WPF way, but, if you already have all the content elements, you could maybe loop through them on load and set the height of the TabControl
programatically.
This worked for me in conjunction with Grid.IsSharedSizeScope
approach shown above.
Note that SetCurrentValue
is used instead of just setting the SelectedIndex
property - this way we keep possible existing bindings:
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);
}