让 WPF Tabcontrol 高度假定最大项目的高度?
-
21-08-2019 - |
题
有没有办法让 tabcontrol 获取最大选项卡项的大小(实际上是 tabitem 的内容)?
由于选项卡控件没有分配特定的大小,因此它应该自动调整大小:它可以正确地执行此操作,但是当您切换选项卡时,它会自动调整自身大小以适应当前所选选项卡内容的高度(和宽度)。
我不希望发生调整大小,并让 tabcontrol 假定最大项目的高度,但仍然让它自动调整大小。
有什么线索吗?我尝试将数据绑定到 Height
用作使用多重绑定的内容的每个元素的属性,同时绑定在 ActualHeight
和 Items
Tab 控件的属性。但可惜的是, ActualHeight
内容元素的个数始终为 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>
...
这可以做到吗?
解决方案 3
事实上,解决起来比我想象的要容易。因为我有一个控制模板 TabControl
无论如何,我设置了高度 ContentPresenter
显示选定的选项卡内容。我使用绑定到项目的转换器来执行此操作 TabControl
, ,必要时测量它们(使用 Measure
)和检查 DesiredSize
适合我需要的尺寸。
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;
}
这工作得很好,但有一些注意事项:
- 每个选项卡内容都应该是
FrameworkElement
- 内容一旦加载就不会改变大小(因为转换器仅在 Items 属性更改时调用,即仅调用一次)。
其他提示
是它可以做到:重用网格rowdefinitions换每个-TabItem的
示例:
<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>
问题是 TabControl
当您切换选项卡时卸载并重新加载其内容。因此它只知道当前活动选项卡中内容的大小。您应该能够更改 TabControl 以便它 绝不 摧毁它的孩子,他们总是存在的(但可能是隐藏的)。
这篇博文 埃里克·伯克(Eric Burke)的著作应该可以帮助你入门。据我所知,通过浏览他的帖子,您需要将其更改为:
- 当
TabControl
已加载。 - 孩子不活动时是躲起来而不是倒下
这可能不是正确的WPF的方式,但是,如果你已经有了所有的内容元素,你也许可以循环通过他们对用电负荷及编程设置TabControl
的高度。
这与上面所示Grid.IsSharedSizeScope
方法结合为我工作。
请注意SetCurrentValue
使用,而不是仅仅设置SelectedIndex
属性 - 这种方式,我们可以保持现有的绑定:
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);
}