如何将WPF TabControl的选项卡分为左侧和右侧?

4

我想要一个TabControl,将一半的选项卡放在左侧,另一半放在右侧,并将内容呈现器放在中间。如下图所示:

enter image description here

我尝试编辑TabControlControlTemplate,用两个StackPanelDockPanel替换TabPanel,代码如下:

<TabControl ItemsSource="{Binding Sequences}" SelectedIndex="0">
    <TabControl.Style>
        <Style TargetType="TabControl">
            <Setter Property="OverridesDefaultStyle"
                    Value="True" />
            <Setter Property="SnapsToDevicePixels"
                    Value="True" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TabControl">
                        <DockPanel>
                            <StackPanel DockPanel.Dock="Left" IsItemsHost="True" Width="100"/>
                            <StackPanel DockPanel.Dock="Right" IsItemsHost="True" Width="100"/>
                            <ContentPresenter ContentSource="SelectedContent" Margin="100,5,5,5" />
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.Style>
    <!-- ... -->
</TabControl>

但是我在每一侧都得到了6个选项卡,左边的选项卡无法使用(没有标题,并且当我点击它们时,在内容呈现器上什么也不显示)。

我如何将 TabControlItemsSource 分割在我的两个 StackPanel 中?

2个回答

1

我不太确定为什么它能工作,但它确实可以。我是通过试图为您解决此问题而偶然发现的。

enter image description here

<TabControl>
    <TabControl.Style>
        <Style TargetType="TabControl" x:Name="myName">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TabControl">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100"/>
                                <ColumnDefinition/>
                                <ColumnDefinition Width="100"/>
                            </Grid.ColumnDefinitions>
                            <StackPanel Name="stk" Grid.Column="0" IsItemsHost="True" Width="100"/>
                            <ItemsControl Grid.Column="2"  ItemsSource="{Binding ElementName=stk, Path=Children}">
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <StackPanel/>
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                            </ItemsControl>
                            <ContentPresenter Grid.Column="1" ContentSource="SelectedContent"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </TabControl.Style>
    <TabItem Header="One">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">1</TextBlock>
    </TabItem>
    <TabItem Header="two">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">2</TextBlock>
    </TabItem>
    <TabItem Header="three">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">3</TextBlock>
    </TabItem>
    <TabItem Header="four">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Black">4</TextBlock>
    </TabItem>
</TabControl>

如果有人能告诉我框架如何决定将哪个项目放在哪里,我会非常好奇!

是的,你的代码可以运行,但我不知道为什么。然而,如果我在TabControl中使用一个items source(<TabControl ItemsSource="{Binding testtab}" SelectedIndex="0">,其中testtab是我的视图模型中等于{1,2,3,4}的列表),而不是在xaml中定义所有选项卡,那么我就可以在左侧看到所有的选项卡。我真的需要在我的TabControl中使用ItemsSource。 - Kantine

0

我不想覆盖我的先前答案,因为对于那些不想绑定itemssource的人来说,它仍然是一个有效的答案。我能够使它看起来正确,但按钮无法工作。也许你有自己如何继续的想法:

enter image description here

    <TabControl ItemsSource="{Binding Controls}">
        <TabControl.Style>
            <Style TargetType="TabControl" x:Name="myName" >
                <Style.Resources>
                    <conv:ObservableCollectionSplitter x:Key="ObsColSplt"/>
                </Style.Resources>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="TabControl">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="100"/>
                                    <ColumnDefinition/>
                                    <ColumnDefinition Width="100"/>
                                </Grid.ColumnDefinitions>
                                <ItemsControl Grid.Column="2" ItemsSource="{TemplateBinding ItemsSource, Converter={StaticResource ObsColSplt}, ConverterParameter=even}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel IsItemsHost="True"/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
                                <ItemsControl Grid.Column="0"  ItemsSource="{TemplateBinding ItemsSource, Converter={StaticResource ObsColSplt}, ConverterParameter=uneven}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel IsItemsHost="True"/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
                                <ContentPresenter Grid.Column="1" ContentSource="SelectedContent"/>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </TabControl.Style>
       
    </TabControl>

还有转换器(不是我最自豪的代码):

public class ObservableCollectionSplitter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            ObservableCollection<TabItem> partialCollection = null;
            if (value != null)
            {
                partialCollection = new ObservableCollection<TabItem>();
                ObservableCollection<TabItem> inputCollection = (value as ObservableCollection<TabItem>);
                int a = 0;
                if (parameter.ToString() == "even")
                {
                    a = 1;
                }
                for (int i = a; i < inputCollection.Count; i = i + 2)
                {
                    partialCollection.Add(inputCollection[i]);
                }
            }
            return partialCollection;

        }//END Convert 

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }//END ConvertBack

    }//END class BooleanInverter : IValueConverter 

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