Пусть высота WPF Tabcontrol предполагает высоту самого большого элемента?
-
21-08-2019 - |
Вопрос
Есть ли какой-нибудь способ заставить tabcontrol принимать размер самого большого элемента вкладки (ну, на самом деле, содержимого tabitem)?
Поскольку tabcontrol не имеет назначенного определенного размера, он должен автоматически изменять размер:он делает это правильно, но при переключении вкладок он автоматически изменяет размер до высоты (и ширины) содержимого текущей выбранной вкладки.
Я не хочу, чтобы происходило изменение размера, и пусть tabcontrol принимает высоту самого большого элемента, но все равно автоматически изменяет его размер.
Есть какие-нибудь зацепки?Я попробовал привязку данных к Height
свойство каждого элемента, используемого в качестве содержимого для использования мультисвязывания, с привязками как к ActualHeight
и тот Items
свойства Tabcontrol.Но, увы, 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
На самом деле, решить эту проблему было проще, чем я думал.Поскольку у меня был controltemplate для 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, т. Е. только один раз).
Другие советы
Да, это можно сделать: повторное использование-grid-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 таким образом, чтобы он никогда уничтожает своих детей, а они всегда присутствуют (но, возможно, скрыты).
Это сообщение в блоге автор: Эрик Берк, это должно помочь вам начать.Из того, что я могу сказать, просмотрев его пост, вам нужно будет изменить его таким образом, чтобы:
- Все дочерние элементы загружаются, когда
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);
}