XAML 中是否有办法使选项卡项标题延伸到选项卡控件的宽度?
例如,我有三个选项卡:红色、蓝色和绿色。如果我有一个宽度设置为自动的选项卡控件,则选项卡标题只会填满选项卡内容上方的部分空间,但我希望它们填满所有空间。对于我的三个选项卡示例,红色应该占据控件的前三分之一,蓝色应该占据中间三分之一,绿色应该占据最后三分之一。
我知道如何在我现在正在处理的代码中执行此操作,但我有兴趣以最简单的方式执行此操作。
我以乔丹为例,对其进行了一些修改。此版本适用于任意数量的选项卡:
namespace WpfApplication1.Converters
{
public class TabSizeConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
TabControl tabControl = values[0] as TabControl;
double width = tabControl.ActualWidth / tabControl.Items.Count;
//Subtract 1, otherwise we could overflow to two rows.
return (width <= 1) ? 0 : (width - 1);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
xaml 中的相同命名空间:
xmlns:local="clr-namespace:WpfApplication1.Converters"
这将使所有选项卡都使用它:
<Window.Resources>
<local:TabSizeConverter x:Key="tabSizeConverter" />
<Style TargetType="{x:Type TabItem}">
<Setter Property="Width">
<Setter.Value>
<MultiBinding Converter="{StaticResource tabSizeConverter}">
<Binding RelativeSource="{RelativeSource Mode=FindAncestor,
AncestorType={x:Type TabControl}}" />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor,
AncestorType={x:Type TabControl}}" Path="ActualWidth" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
每个人似乎都在使用转换器路线,但实际上就像在模板中UniformGrid
使用Rows
设置为 1的. 当然,您将不得不重新模板化,但这还不错。TabControl
TabPanel
我可以使用这样的转换器来做到这一点:
namespace WpfApplication1.Converters
{
public class SizeConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
double width = Double.Parse(value.ToString());
//Subtract 1, otherwise we could overflow to two rows.
return .25 * width - 1;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
#endregion
}
}
然后将命名空间添加到我的 xaml:
xmlns:local="clr-namespace:WpfApplication1.Converters"
然后让所有 TabItems 使用转换器:
<Window.Resources>
<local:SizeConverter x:Key="sizeConverter" />
<Style TargetType="{x:Type TabItem}">
<Setter Property="Width" Value="{Binding ElementName=x_Grid, Path=ActualWidth, Converter={StaticResource sizeConverter}}" />
</Style>
</Window.Resources>
x_Grid 是父元素的 x:Name 我希望选项卡是 1/4,如果这有意义的话。
我是一个老派风格的人。并且更喜欢将这种功能封装到控件本身的代码中。我的派生控件如下所示:
public class CustomTabControl :TabControl
{
protected override void OnRenderSizeChanged(System.Windows.SizeChangedInfo sizeInfo)
{
foreach (TabItem item in this.Items)
{
double newW = (this.ActualWidth / Items.Count) - 1;
if (newW < 0) newW = 0;
item.Width = newW;
}
}
}
我的 XAML 看起来像
</infrastructure:CustomTabControl>
<TabItem />
<TabItem />
</infrustracture:CustomControl>
有人可以解释为什么每个人都喜欢样式控制而不是派生。
通过将宽度绑定到父选项卡控件的 ActualWidth 是可能的,如下所示。
我已经将它包装成一种样式以应用于所有标签页。
<Grid>
<Grid.Resources>
<Style TargetType="TabItem">
<Setter Property="Width" Value="{Binding
Path=ActualWidth,
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type TabControl}}}"/>
</Style>
</Grid.Resources>
<TabControl>
<TabItem Header="Page3"/>
<TabItem Header="Page2"/>
<TabItem Header="Page3"/>
</TabControl>
</Grid>
我通过创建一个特殊的转换器解决了这个问题:
public class TabItemWidthAdjustmentConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Double lTabControlWidth = value is Double ? (Double)value : 50; // 50 just to see something, in case of error
Int32 lTabsCount = (parameter != null && parameter is String) ? Int32.Parse((String)parameter) : 1;
return lTabControlWidth / lTabsCount;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
我在 TabControl 的 Tag 元素中计算一个选项卡项的值,以避免单独为每个选项卡计算它。这是示例代码(请注意,在我的情况下,我需要一个水平 ScrollViewer,因为我有多个选项卡项,并且具有最小宽度):
<TabControl Name="tabControl" VerticalAlignment="Stretch" SelectionChanged="TabControl_SelectionChanged"
Tag="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={StaticResource tabItemWidthAdjustmentConverter}, ConverterParameter=15}"><!-- Here 15 because I have 15 tabs -->
<TabControl.Template>
<ControlTemplate TargetType="TabControl">
<StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<TabPanel x:Name="HeaderPanel"
Panel.ZIndex="1"
KeyboardNavigation.TabIndex="1"
IsItemsHost="True"/>
</ScrollViewer>
<ContentPresenter x:Name="PART_SelectedContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="{TemplateBinding Padding}"
ContentSource="SelectedContent"/>
</StackPanel>
</ControlTemplate>
</TabControl.Template>
<TabItem Header="Tab1" MinWidth="115" VerticalAlignment="Stretch" Width="{Binding ElementName=tabControl, Path=Tag}">
<ContentControl ContentTemplate="{StaticResource My_TemplateTab1}">
<ContentPresenter />
</ContentControl>
</TabItem>
<TabItem Header="Tab2" MinWidth="115" Height="50" Width="{Binding ElementName=tabControl, Path=Tag}">
<ContentControl ContentTemplate="{StaticResource My_TemplateTab2}">
<ContentPresenter />
</ContentControl>
</TabItem>
<!-- Here another 13 tabs which I skipped -->
</TabControl>
我可以说这对我来说就像一个魅力:) 希望有人会觉得它有用!
PS 在我的情况下,我不需要/想要任何风格。
这是一个仅使用模板的无痛解决方案:
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:EffectLibrary="clr-namespace:EffectLibrary;assembly=EffectLibrary"
mc:Ignorable="d"
Title="Window1" Height="300" Width="300">
<TabControl Style="{DynamicResource TabControlStyle}" ItemContainerStyle="{DynamicResource TabItemStyle}" BorderBrush="{DynamicResource Pallete.Primary}" Foreground="{DynamicResource Pallete.Primary}" Background="Transparent" Margin="0" d:LayoutOverrides="Height">
<TabControl.Resources>
<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="#093A5F"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="#001423"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Border x:Name="Bg" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<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>
<UniformGrid x:Name="headerPanel" IsItemsHost="True" Margin="0">
<UniformGrid.Style>
<Style TargetType="{x:Type UniformGrid}">
<Setter Property="Rows" Value="1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource TemplatedParent}}" Value="Right">
<Setter Property="Columns" Value="1"/>
<Setter Property="Rows" Value="0"/>
</DataTrigger>
<DataTrigger Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource TemplatedParent}}" Value="Left">
<Setter Property="Columns" Value="1"/>
<Setter Property="Rows" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UniformGrid.Style>
</UniformGrid>
<Border x:Name="contentPanel" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local" BorderThickness="0,1,0,0" BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="Grid.Row" TargetName="headerPanel" Value="1"/>
<Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="Grid.Row" TargetName="headerPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="headerPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="contentPanel" Value="1"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="Grid.Row" TargetName="headerPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="headerPanel" Value="1"/>
<Setter Property="Grid.Column" TargetName="contentPanel" Value="0"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Effect" TargetName="templateRoot">
<Setter.Value>
<EffectLibrary:DesaturateEffect DesaturationFactor=".25"/>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}}"/>
<Setter Property="Background" Value="{Binding Background, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}}"/>
<Setter Property="BorderBrush" Value="{Binding BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}}"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0,5"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid x:Name="templateRoot" SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
<Border x:Name="mainBorder" BorderBrush="{TemplateBinding BorderBrush}">
<Border x:Name="highlightBorder"/>
</Border>
<ContentPresenter x:Name="contentPresenter" ContentSource="Header" Focusable="False" HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Effect" TargetName="templateRoot">
<Setter.Value>
<EffectLibrary:DesaturateEffect DesaturationFactor=".25"/>
</Setter.Value>
</Setter>
</Trigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="true">
<Setter TargetName="highlightBorder" Property="Background" Value="#0B79CE"/>
</DataTrigger>
<DataTrigger Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}" Value="Top">
<Setter TargetName="mainBorder" Property="BorderThickness" Value="0,0,1,0"/>
<Setter TargetName="highlightBorder" Property="Height" Value="2"/>
<Setter TargetName="highlightBorder" Property="VerticalAlignment" Value="Bottom"/>
</DataTrigger>
<DataTrigger Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}" Value="Bottom">
<Setter TargetName="mainBorder" Property="BorderThickness" Value="0,0,1,0"/>
<Setter TargetName="highlightBorder" Property="Height" Value="2"/>
<Setter TargetName="highlightBorder" Property="VerticalAlignment" Value="Top"/>
</DataTrigger>
<DataTrigger Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}" Value="Left">
<Setter TargetName="mainBorder" Property="BorderThickness" Value="0,0,0,1"/>
<Setter TargetName="highlightBorder" Property="Width" Value="2"/>
<Setter TargetName="highlightBorder" Property="HorizontalAlignment" Value="Right"/>
</DataTrigger>
<DataTrigger Binding="{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}" Value="Right">
<Setter TargetName="mainBorder" Property="BorderThickness" Value="0,0,0,1"/>
<Setter TargetName="highlightBorder" Property="Width" Value="2"/>
<Setter TargetName="highlightBorder" Property="HorizontalAlignment" Value="Left"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Header="Years">
<ListBox Background="{DynamicResource Pallete.Primary.Brightest}" Foreground="{DynamicResource Pallete.Primary}">
<TextBlock Text="2015"/>
<TextBlock Text="2016"/>
<TextBlock Text="2017"/>
</ListBox>
</TabItem>
<TabItem Header="Tables">
<ListBox Background="{DynamicResource Pallete.Primary.Brightest}" Foreground="{DynamicResource Pallete.Primary}">
<TextBlock Text="Table1..."/>
<TextBlock Text="Table2..."/>
<TextBlock Text="Table3..."/>
</ListBox>
</TabItem>
</TabControl>
</Window>
希望我已经包含了所有颜色,它会为你工作。啊……啪!我的去饱和效果!我的 WPF 启动项目,您可以根据需要从那里获取该效果(在触发器中添加效果比重新着色所有内容更容易,与高光相同)。是的,这是很多代码,但我只是将 ItemsContainer 更改为更好看,并用 UniformGrid 替换标准 Header 控件,并根据 TabStripPlacement 将 Rows 或 Columns 设置为 1。现在我可以折叠这段代码,或者把它藏在某个地方。:)
我听从了查理的建议,继续重新设计路线。这是一个简单的实现,TabControl
它在它的 s 之间平均分配可用空间TabItem
,使用UniformGrid
:
控件的 XAML
<TabControl x:Class="YourNamespace.Views.BigTabsTabControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:YourNamespace.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Padding="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
BorderThickness="1" Foreground="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}">
<TabControl.Resources>
<SolidColorBrush x:Key="TabItem.Selected.Background" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TabItem.Selected.Border" Color="#ACACAC"/>
</TabControl.Resources>
<TabControl.Style>
<Style TargetType="{x:Type TabControl}">
<Setter Property="Background" Value="{StaticResource TabItem.Selected.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource TabItem.Selected.Border}"/>
</Style>
</TabControl.Style>
<TabControl.Template>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<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>
<UniformGrid x:Name="headerPanel" Background="Transparent" Grid.Column="0" IsItemsHost="true" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1" />
<Border x:Name="contentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="Grid.Row" TargetName="headerPanel" Value="1"/>
<Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
<Setter Property="Margin" TargetName="headerPanel" Value="2,0,2,2"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="Grid.Row" TargetName="headerPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="headerPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="contentPanel" Value="1"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<Setter Property="Margin" TargetName="headerPanel" Value="2,2,0,2"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="Grid.Row" TargetName="headerPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="contentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="headerPanel" Value="1"/>
<Setter Property="Grid.Column" TargetName="contentPanel" Value="0"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<Setter Property="Margin" TargetName="headerPanel" Value="0,2,2,2"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</TabControl.Template>
</TabControl>
控制的代码隐藏
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace YourNamespace.Views
{
/// <summary>
/// A TabControl with large tabs.
/// </summary>
public partial class BigTabsTabControl : TabControl
{
public BigTabsTabControl()
{
InitializeComponent();
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (this.Template != null)
{
UniformGrid X = this.Template.FindName("headerPanel", this) as UniformGrid;
if (X != null) X.Columns = this.Items.Count;
}
}
}
}
就是这样。您现在可以将TabItem
s 添加到此控件,它们将自动调整其宽度。也不需要Grid.Column
为这些TabItem
s 指定,即使在设计时,它们也可以在没有它的情况下正常工作。
我不知道它是否适用于标签,但每当我需要拉伸任何东西来填充容器时,我都会使用ViewBox。这就是你要找的东西吗?
除了 Ryan Versaw 接受的提供相等 tabItem 标题宽度的解决方案之外,我还发现了以下方法使其依赖于每个标题的长度。
首先,我们通过将此行添加到 xaml 多重绑定来获取每个 tabItem 标头的字符串。这样就变成了:
<MultiBinding Converter="{StaticResource tabSizeConverter}">
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}" />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}" Path="ActualWidth" />
<Binding Path="Header" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
Converter 中还有一些代码(values[] 也获得了 tabItem Header):
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
TabControl tabControl = values[0] as TabControl;
string AllHeaders = "";
for (int i = 0; i < tabControl.Items.Count; i++)
{
int index = tabControl.Items[i].ToString().IndexOf("Header:") + "Header:".Length;
string currentHeader = tabControl.Items[i].ToString().Substring(index);
currentHeader = currentHeader.Substring(0, currentHeader.Length - " Content:".Length);
AllHeaders += currentHeader;
}
//Normalize width according to header length
double width = values[2].ToString().Length * tabControl.ActualWidth / AllHeaders.Length;
//Subtract 1, otherwise we could overflow to two rows.
var retVal = (width <= 1) ? 0 : (width - 1);
return retVal;
}
我怀疑可能有一种更有效的方法来获取所有标题的 AllHeaders 字符串,但它可以正常工作......
我正在使用以下解决方案:在主窗口中,我使用窗口调整大小事件和 tabcontrol Initialized 事件来设置每个选项卡的宽度。数字“5”对应于我的标签数量。
private void tabchanger_Initialized(object sender, EventArgs e)
{
foreach (TabItem item in tabchanger.Items)
{
double newW = (tabchanger.ActualWidth / 5) - 1;
if (newW < 0) newW = 0;
item.Width = newW;
}
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
foreach (TabItem item in tabchanger.Items)
{
double newW = (tabchanger.ActualWidth / 5) - 1;
if (newW < 0) newW = 0;
item.Width = newW;
}
}
这是最快速的解决方案:
<TabControl.Template>
<ControlTemplate TargetType="TabControl">
<DockPanel>
<UniformGrid IsItemsHost="True" Rows="1" DockPanel.Dock="Top"></UniformGrid>
<ContentPresenter ContentSource="SelectedContent"></ContentPresenter>
</DockPanel>
</ControlTemplate>
</TabControl.Template>