如何向 WPF TabControl 添加额外内容?

8
我有一个自定义的TabControl ControlTemplate,为TabControl的头部添加了按钮。目前这个ControlTemplate没有命名部分,因为按钮命令是在ControlTemplate的XAML中绑定的,不需要在ControlTemplate外部公开。
对于按钮来说,这很好,但如果我想向TabItemHeaders的左(或右)侧添加内容,并将其绑定到ControlTemplate以外,使我的TabControl更加灵活呢?
我的想法是对TabControl进行子类化,并在ControlTemplate中添加两个命名部分,并将这些作为新控件的属性公开; CustomTabControl.LeftContentArea和CustomTabControl.RightContentArea。每个命名部分都是一个ContentPresenter,每个ContentPresenter的Content属性均由上述命名的属性公开。
然而,当我尝试这样做时,我无法将内容放置在左侧和右侧内容区域中。
编辑:为了清楚起见,我包含了一张图片。红色矩形显示了我想要放置额外内容的位置。
更新:下面是我迄今为止取得的进展截图,希望这能更好地解释我的问题。
屏幕截图显示了我的自定义Tab Control,其中有两个空选项卡和三个按钮,这些按钮当前位于TabItem头区域的右侧。这些按钮当前在TabControls的自定义ControlTemplate中定义,即Grid中有一个ColumnDefinition,其中包含一个StackPanel,用于承载3个按钮。
我正在寻找一种方式,允许选项卡控件的消费者决定将什么内容放在选项卡旁边的区域。例如,用户应该能够执行以下操作:
<local:CustomTabControl>
    <local:CustomTabControl.RightContentArea>
        <!-- This can be changed to ANY content that the user wants -->
        <StackPanel Orientation="Horizontal">
            <Button Content="Test" />
            <Button Content="Test" />
            <Button Content="Test" />
        </StackPanel>
    </local:CustomTabControl.RightContentArea>

    <!-- TabItems are added as normal -->
    <TabItem Header="Tab One" />
    <TabItem Header="Tab Two" />

</local:CustomTabControl>
2个回答

6
我尝试了一种不同(懒惰)的方法,即创建另一个网格,占据与TabControl相同的空间,即两者都在Grid.Row = 0中。我已将网格高度绑定到第一个选项卡的高度,因此如果选项卡的高度发生变化,则其他控件将保持居中。我在窗口上设置了MinWidth,以使控件不重叠选项卡。
将此代码粘贴到新的WPF窗口中...
<Window x:Class="MainWindow"
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"
mc:Ignorable="d"
Title="MainWindow" Height="306" Width="490" MinWidth="300">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <TabControl Grid.Row="0" x:Name="tabControl">
        <TabItem x:Name="tabItem" Header="TabItem" Height="50">
            <Grid Background="#FFE5E5E5"/>
        </TabItem>
        <TabItem Header="TabItem">
            <Grid Background="#FFE5E5E5"/>
        </TabItem>
    </TabControl>

    <Grid Grid.Row="0" Height="{Binding ActualHeight, ElementName=tabItem}" 
       VerticalAlignment="Top" Margin="0,2,0,0">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" 
                VerticalAlignment="Center" Margin="20,0">
            <TextBlock VerticalAlignment="Center" Margin="10,0" FontSize="16" 
                   Foreground="Red" FontFamily="Calibri">My Text</TextBlock>
            <Button Content="My Button" />
        </StackPanel>
    </Grid>

</Grid>
</Window>

当你完成这个步骤后,你会得到以下结果:

输入图像描述


3

根据您需要的灵活性程度,有一些方法比其他方法更适合,如果可能的话,我会尝试使用DynamicResources,因为通常比创建新用户控件更少麻烦。

以下是如何在选项卡标题左侧添加其他内容的示例:

<TabControl>

    <TabControl.Resources>
        <DataTemplate x:Key="AugmentedTabItem">
            <StackPanel Orientation="Horizontal">
                <ContentPresenter Content="{DynamicResource ContentLeft}" Margin="0,0,5,0"/>
                <ContentPresenter Content="{Binding}"/>
            </StackPanel>
        </DataTemplate>     
    </TabControl.Resources>

    <TabItem Header="ÜberTab" HeaderTemplate="{StaticResource AugmentedTabItem}">
       <TabItem.Resources>
            <TextBlock x:Key="ContentLeft" Text=">>>" Foreground="Blue"/>           

        </TabItem.Resources>
    </TabItem>      
</TabControl>

希望这可以帮到您,如果有不清楚的地方或者这不够满足您的需求,请在评论区留言。

我正在寻找一种方法来公开自定义控件中的属性,以便我可以在XAML中像这样绑定它:LeftContentArea="{StaticResource MyPanelWithLotsOfButtonsControl}"。自定义内容需要位于TabItems的左侧而不是标题的左侧。这确实帮助了我另一个问题,所以一旦我有足够的声望,我会点赞。谢谢。 - Benjamin Gale
你实际上也可以绑定到那些资源。通过TabItems的左侧,你是指所有选项卡左侧的标题区域吗? - H.B.
是的。在我的自定义控件模板中,我添加了一个额外的ColumnDefinition,以便选项卡偏移并留出空间来添加我的额外内容。我想公开一个属性,允许我将内容放入此区域。 - Benjamin Gale
你需要的是一个相当复杂的扩展,因为你需要重写TabControl的ControlTemplate来容纳那些区域。我遇到的一个问题是,相对于Horizontal和VerticalAlignment属性的绑定不再起作用,因为需要改变可视树,这在某种程度上破坏了布局。 - H.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接