Каждый TabItem
звучит так, как будто он рисуется отдельно. Обычно WPF выгружает TabItems, которые не видны, поэтому во время изменения размера окна существует только одна WrapPanel, которая существует. Когда вы перезагружаете TabItem путем переключения вкладок, если что-то не связано (например, ActualHeight), тогда он перезагрузится к своим исходным значениям, определенным в вашем XAML
Обычно я предпочитаю хранить свои размеры в процентах, а затем использовать конвертер для преобразования процента в фактический размер
Конвертер, который я обычно использую, находится ниже. Я создал это, когда впервые начал работать с WPF, и я не знал, что в то время существовали мультиконвертеры. Я уверен, что он может быть переписан как мультиконвертер, однако я еще не удосужился сделать это.
Чтобы использовать его, добавьте конвертер в свои ресурсы
<local:PercentOfParentConverter x:Key="PanelHeightConverter" />
<local:PercentOfParentConverter x:Key="PanelWidthConverter" />
Установите привязки на основе конвертера
<Setter Property="Height" Value="{Binding Path=PanelHeight,
Converter={StaticResource PanelHeightConverter}}" />
<Setter Property="Width" Value="{Binding Path=PanelWidth,
Converter={StaticResource PanelWidthConverter}}" />
А в Code-Behind обязательно подключитесь к событию SizeChanged
, чтобы обновить ParentSize
конвертера при каждом изменении размера
// If workarea size changes, reposition/resize panels within it to keep the same layout
private void PanelSizeChanged(object sender, SizeChangedEventArgs e)
{
Panel c = sender as Panel;
if (c != null)
{
// Set the parent's height/width on the converter
PercentOfParentConverter sizeConverter = (PercentOfParentConverter)c.FindResource("PanelHeightConverter");
if (sizeConverter != null) sizeConverter.ParentSize = c.ActualHeight;
sizeConverter = (PercentOfParentConverter)c.FindResource("PanelWidthConverter");
if (sizeConverter != null) sizeConverter.ParentSize = c.ActualWidth;
foreach (UIElement child in c.Children)
{
RebindPanelSizeAndPosition(child);
}
}
}
// Refreshes the Panel.Height/Width bindings of the UIElement passed to it
private void RebindPanelSizeAndPosition(UIElement element)
{
BindingOperations.GetBindingExpressionBase(element, Panel.HeightProperty).UpdateTarget();
BindingOperations.GetBindingExpressionBase(element, Panel.WidthProperty).UpdateTarget();
}
Фактический код конвертера выглядит следующим образом:
// Converts a percent to a double value based on the parent size set
public class PercentOfParentConverter : IValueConverter
{
public double ParentSize { get; set; }
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var percent = (double) value;
return percent*ParentSize;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (ParentSize != 0)
{
return (double) value/ParentSize;
}
else
{
return 0;
}
}
#endregion
}