我的要求是使用最大宽度为180像素的标签项目的标签控件,如果标签不适合窗口,则将标签项目大小缩小到最多60像素。如果选项卡不适合窗口大小,还要显示带有选项卡标题的下拉列表。根据我有限的知识,我觉得我需要创建一个扩展面板的自定义控件,比如SqueezeTabPanel:Panel并覆盖 MeasureOverride和ArrangeOverride方法根据窗口大小计算每个tabitems的含义。
但我不确定如何在此基础上添加下拉列表的要求。截至目前,我已经为挤压面板创建了一个控件模板
<Style TargetType="TabControl" x:Key="SqueezeTabPanel">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid KeyboardNavigation.TabNavigation="Local" SnapsToDevicePixels="true"
ClipToBounds="true">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0"/>
<ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0" Height="Auto"/>
<RowDefinition x:Name="RowDefinition1" Height="*"/>
</Grid.RowDefinitions>
<customControl:SqueezeTabPanel
x:Name="HeaderPanel" Panel.ZIndex ="1" KeyboardNavigation.TabIndex="1" Grid.Column="0"
Grid.Row="0" Margin="8,0,4,-1" IsItemsHost="true" Background="Transparent"/>
<Border x:Name="ContentPanel"
Background="{StaticResource PrimaryTextBoxColor}"
BorderThickness= "1" CornerRadius="2"
BorderBrush="{TemplateBinding BorderBrush}"
KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2"
Grid.Column="0"
Grid.Row="1">
<ContentPresenter
x:Name="PART_SelectedContentHost"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="4"
ContentSource="SelectedContent"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TabItem}" >
<Setter Property="FontSize" Value="{StaticResource SecondarySmallText}"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Width" Value="180"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid >
<Grid.ToolTip >
<ToolTip Visibility="{TemplateBinding IsSelected,Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBlock Text="{TemplateBinding Header}" x:Name ="TabToolTip"/>
</ToolTip>
</Grid.ToolTip>
<Border Name="Border" Margin="0,0,-4,4" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="0,5,0,0" Height="24">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center"
ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True" Height="20"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100" />
<Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedTabItemBackground}" />
<Setter TargetName="Border" Property="BorderThickness" Value="1" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource PrimaryBorderBrush}" />
<Setter Property="Foreground" Value="{StaticResource PrimaryTextColor}" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource PrimaryBackground}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledTextColor}"/>
<Setter TargetName="Border" Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{StaticResource DisabledTextColor}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我对SqueezeTabPanel的自定义控件是
public class SqueezeTabPanel : Panel
{
private double _rowHeight;
private double _scaleFactor;
// Ensure tabbing works correctly
static SqueezeTabPanel()
{
KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(SqueezeTabPanel), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));
KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(SqueezeTabPanel), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle));
}
// This Panel lays its children out horizontally.
// If all children cannot fit in the allocated space,
// the available space is divided proportionally between them.
protected override Size MeasureOverride(Size availableSize)
{
// See how much room the children want
double minwidthrequired = 60;
double width = 0.0;
this._rowHeight = 0.0;
foreach (UIElement element in this.Children)
{
element.Measure(availableSize);
Size size = this.GetDesiredSizeLessMargin(element);
this._rowHeight = Math.Max(this._rowHeight, size.Height);
width += size.Width;
}
// If not enough room, scale the
// children to the available width
if (width > availableSize.Width)
{
this._scaleFactor = availableSize.Width / width;
width = 0.0;
foreach (UIElement element in this.Children)
{
double itemWidth = element.DesiredSize.Width * this._scaleFactor;
if (itemWidth>=60)
element.Measure(new Size(itemWidth, availableSize.Height));
else
element.Measure(new Size(minwidthrequired, availableSize.Height));
width += element.DesiredSize.Width;
}
}
else
this._scaleFactor = 1.0;
return new Size(width, this._rowHeight);
}
// Perform arranging of children based on the final size
protected override Size ArrangeOverride(Size arrangeSize)
{
Point point = new Point();
foreach (UIElement element in this.Children)
{
Size size1 = element.DesiredSize;
Size size2 = this.GetDesiredSizeLessMargin(element);
Thickness margin = (Thickness)element.GetValue(FrameworkElement.MarginProperty);
double width = size2.Width;
if (element.DesiredSize.Width != size2.Width)
width = arrangeSize.Width - point.X;
element.Arrange(new Rect(
point,
new Size(Math.Min(width, size2.Width), this._rowHeight)));
double leftRightMargin = Math.Max(0.0, -(margin.Left + margin.Right));
point.X += size1.Width + (leftRightMargin * this._scaleFactor);
}
return arrangeSize;
}
// Return element's size
// after subtracting margin
private Size GetDesiredSizeLessMargin(UIElement element)
{
Thickness margin = (Thickness)element.GetValue(FrameworkElement.MarginProperty);
Size size = new Size();
size.Height = Math.Max(0.0, element.DesiredSize.Height - (margin.Top + margin.Bottom));
size.Width = Math.Max(0.0, element.DesiredSize.Width - (margin.Left + margin.Right));
return size;
}
}
我不确定我的方法是否正确。请给出正确的方向帮助。提前致谢