【问题标题】:How to change the overlapping order of TabItems in WPF TabControl如何更改 WPF TabControl 中 TabItems 的重叠顺序
【发布时间】:2011-01-14 12:35:09
【问题描述】:

我已经使用 Path 对象创建了垂直 TabItems。选定的 TabItem 与未选定的 TabItem 重叠,这很好用。重叠是通过在 TabItem 模板中设置负边距来完成的。

对于现在未选中的 TabItem,一个 TabItem 与下面的 TabItem 重叠。例如图片中 Tab 4 与 Tab 3 重叠,Tab 3 与 Tab 2 重叠。

我想更改未选中的 Tab Items 的重叠顺序,以便未选中的 TabItem 与下方的 TabItem 重叠,并与上方的 TabItem 重叠,例如Tab 2 与 Tab 3 重叠,Tab 3 与 Tab 4 重叠。

我尝试过设置 TabPanel 的 FlowDirection 属性,但这不起作用。

我怎样才能做到这一点?任何帮助表示赞赏。提前致谢!

未选中的 TabItem 重叠错误:

XAML 代码:

<Style x:Key="styleMainNavTabControl" TargetType="{x:Type TabControl}">
    <Setter Property="TabStripPlacement" Value="Left" />
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="200"/>
                    </Grid.ColumnDefinitions>
                    <Border Grid.Column="0" Background="White" BorderBrush="Black" BorderThickness="0,0,1,0" Padding="20">
                        <ContentPresenter ContentSource="SelectedContent" />
                    </Border>
                    <Border Grid.Column="1" Padding="0,30,10,0" Background="#F7F3F7">
                        <TabPanel Panel.ZIndex="1" Margin="-1,0,0,0" FlowDirection="RightToLeft" IsItemsHost="True" Background="Transparent"/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="styleMainNavTabItem" TargetType="{x:Type TabItem}">
    <Setter Property="MinHeight" Value="90" />
    <Setter Property="FontSize" Value="14" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <Grid Margin="0,0,0,-35">
                    <Path Name="TabPath" Stroke="Black" StrokeThickness="1" Fill="LightGray" Data="M 0,0 a 10,10 0 0 0 10,10 h 150 a 20,20 0 0 1 20,20 v 60 a 20,20 0 0 1 -20,20 h -150 a 10,10 0 0 0 -10,10 z" />
                    <ContentPresenter ContentSource="Header" Margin="10,2,10,2" VerticalAlignment="Center" TextElement.Foreground="#FF000000"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Panel.ZIndex" Value="100" />
                        <Setter TargetName="TabPath" Property="Fill" Value="White" />
                        <Setter TargetName="TabPath" Property="Data" Value="M 0,0 a 10,10 0 0 0 10,10 h 150 a 20,20 0 0 1 20,20 v 60 a 20,20 0 0 1 -20,20 h -150 a 10,10 0 0 0 -10,10" />
                    </Trigger>
                    <Trigger Property="IsSelected" Value="False">
                        <Setter Property="Panel.ZIndex" Value="90" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

【问题讨论】:

    标签: .net wpf tabcontrol


    【解决方案1】:

    我认为最简单的方法是使用 MultiBinding/Converter,它使用父级的 ItemsContainerGenerator 来确定 ZIndex。它看起来像这样:

    public class TabZIndexConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var tabItem = values[0] as TabItem;
            var tabControl = values[1] as TabControl;
            if (tabItem == null || tabControl == null) return Binding.DoNothing;
    
            var count = (int)values[2];
    
            var index = tabControl.ItemContainerGenerator.IndexFromContainer(tabItem);
    
            return count - index;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    

    然后,您将更改 TabItem 样式以在 setter 中设置 ZIndex(并删除第二个触发器,因为它将禁用此 setter):

    <Style x:Key="styleMainNavTabItem" TargetType="{x:Type TabItem}">
        <Setter Property="Panel.ZIndex">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource tabZIndexConverter}">
                    <Binding RelativeSource="{RelativeSource Self}" />
                    <Binding RelativeSource="{RelativeSource AncestorType={x:Type TabControl}}" />
                    <Binding Path="Items.Count" RelativeSource="{RelativeSource AncestorType={x:Type TabControl}}" />
                </MultiBinding>
            </Setter.Value>
        </Setter>
        ...
    </Style>
    

    【讨论】:

    • 您的解决方案运行良好!除了行“var index = tabControl.ItemContainerGenerator.IndexFromContainer(tabItem);”总是返回-1,所以我使用“int index = tabControl.Items.IndexOf(tabItem);”反而。现在它起作用了。非常感谢!
    • 啊,我猜那是因为您直接使用 TabItems,而不是 ItemsSource。我认为 ItemContainerGenerator 在这种情况下仍然可以工作,但显然我错了。很高兴它对你有用!
    • Cheers =) 我将此代码用于通用 TabControl,这给我带来了麻烦。因为我不想将 ZIndex 硬编码到 Selected 触发器中,所以我将这个 Setter 转储到 SelectedNot Selected 触发器中.然后我修改了返回值:if(tabItem.IsSelected) return count; else return count-index;
    猜你喜欢
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多