want to make scrollable tabs for a tabcontrol

后端 未结 6 763
故里飘歌
故里飘歌 2020-12-05 14:22

Say I have a tab control, and I have over 50 tabs, where there is no enough space to hold so many tabs, how make these tabs scrollable?

相关标签:
6条回答
  • 2020-12-05 14:40

    For thoose who want to know how to make the scrollviewer scroll to the selected tab item.

    Add this event SelectionChanged="TabControl_SelectionChanged" to your TabControl.

    Then give a name like TabControlScroller to the ScrollViewer inside the template. You should end with something like this

    <TabControl SelectionChanged="TabControl_SelectionChanged">
          <TabControl.Template>
              <ControlTemplate TargetType="TabControl">
                  <Grid>
                      <Grid.RowDefinitions>
                          <RowDefinition Height="Auto" />
                          <RowDefinition />
                      </Grid.RowDefinitions>
                      <ScrollViewer x:Name="TabControlScroller" HorizontalScrollBarVisibility="Hidden"  VerticalScrollBarVisibility="Hidden" >
                          <TabPanel x:Name="HeaderPanel"
                              Panel.ZIndex ="1" 
                              KeyboardNavigation.TabIndex="1"
                              Grid.Column="0"
                              Grid.Row="0"
                              Margin="2,2,2,0"
                              IsItemsHost="true"/>
                      </ScrollViewer>
                      <ContentPresenter x:Name="PART_SelectedContentHost"
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                          Margin="{TemplateBinding Padding}"
                          ContentSource="SelectedContent" Grid.Row="1"/>
                  </Grid>
              </ControlTemplate>
          </TabControl.Template>
         <!-- Your Tabitems-->
    </TabControl>
    

    Then in code behind you just have to add this method :

    private void TabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        TabControl tabControl = (TabControl)sender;
        ScrollViewer scroller = (ScrollViewer)tabControl.Template.FindName("TabControlScroller", tabControl);
        if (scroller != null)
        {
            double index = (double)(tabControl.SelectedIndex );
            double offset = index * (scroller.ScrollableWidth / (double)(tabControl.Items.Count));
            scroller.ScrollToHorizontalOffset(offset);
        }
    }
    
    0 讨论(0)
  • 2020-12-05 14:43

    Place it inside a ScrollViewer.

    <ScrollViewer  HorizontalScrollBarVisibility="Auto"  VerticalScrollBarVisibility="Hidden">
        <TabControl ...>
             ...
        </TabControl>
    
    </ScrollViewer>
    
    0 讨论(0)
  • 2020-12-05 14:48

    The above solution is great for tab items with the tab control's "TabStripPlacement" property set to "Top". But if you are looking to have your tab items, say to the left side, then you will need to change a few things.

    Here is a sample of how to get the scrollviewer to work with the TabStripPlacement to the Left:

    <TabControl.Template>
    <ControlTemplate TargetType="TabControl">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <ScrollViewer 
                HorizontalScrollBarVisibility="Disabled"  
                VerticalScrollBarVisibility="Auto" 
                FlowDirection="RightToLeft">
                    <TabPanel 
                        x:Name="HeaderPanel"
                        Panel.ZIndex ="0" 
                        KeyboardNavigation.TabIndex="1"
                        IsItemsHost="true"
                    />
            </ScrollViewer>
            <ContentPresenter 
                x:Name="PART_SelectedContentHost"
                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                ContentSource="SelectedContent" Grid.Column="1"
            />
        </Grid>
    </ControlTemplate>
    

    Note that in the ScrollViewer I set FlowDirection="RightToLeft" so that the scroll bar would snap to the left of the tab items. If you are placing your tab items to the right the you will need to remove the FlowDirection property so that it defaults to the right side.

    And here is the result:

    0 讨论(0)
  • 2020-12-05 14:49

    Override the TabControl ControlTemplate and add a ScrollViewer around the TabPanel like this sample:

    <Grid>
        <TabControl>
            <TabControl.Template>
                <ControlTemplate TargetType="TabControl">
                    <StackPanel>
                        <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
                            <TabPanel x:Name="HeaderPanel"
                                  Panel.ZIndex ="1" 
                                  KeyboardNavigation.TabIndex="1"
                                  Grid.Column="0"
                                  Grid.Row="0"
                                  Margin="2,2,2,0"
                                  IsItemsHost="true"/>
                        </ScrollViewer>
                        <ContentPresenter x:Name="PART_SelectedContentHost"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              Margin="{TemplateBinding Padding}"
                                              ContentSource="SelectedContent"/>
                    </StackPanel>
                </ControlTemplate>
            </TabControl.Template>
            <TabItem Header="TabItem1">TabItem1 Content</TabItem>
            <TabItem Header="TabItem2">TabItem2 Content</TabItem>
            <TabItem Header="TabItem3">TabItem3 Content</TabItem>
            <TabItem Header="TabItem4">TabItem4 Content</TabItem>
            <TabItem Header="TabItem5">TabItem5 Content</TabItem>
            <TabItem Header="TabItem6">TabItem6 Content</TabItem>
            <TabItem Header="TabItem7">TabItem7 Content</TabItem>
            <TabItem Header="TabItem8">TabItem8 Content</TabItem>
            <TabItem Header="TabItem9">TabItem9 Content</TabItem>
            <TabItem Header="TabItem10">TabItem10 Content</TabItem>
        </TabControl>
    </Grid>
    

    which gives this result:

    TabControlScroll

    0 讨论(0)
  • 2020-12-05 14:52

    Rick's answer actually breaks the vertical stretching of content inside the tabcontrol. It can be improved to retain vertical stretching by using a two row grid instead of a StackPanel.

    <TabControl.Template>
                <ControlTemplate TargetType="TabControl">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <ScrollViewer HorizontalScrollBarVisibility="Auto"  VerticalScrollBarVisibility="Hidden" >
                            <TabPanel x:Name="HeaderPanel"
                              Panel.ZIndex ="1" 
                              KeyboardNavigation.TabIndex="1"
                              Grid.Column="0"
                              Grid.Row="0"
                              Margin="2,2,2,0"
                              IsItemsHost="true"/>
                        </ScrollViewer>
                        <ContentPresenter x:Name="PART_SelectedContentHost"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                          Margin="{TemplateBinding Padding}"
                                          ContentSource="SelectedContent" Grid.Row="1"/>
                    </Grid>
                </ControlTemplate>
            </TabControl.Template>
    
    0 讨论(0)
  • 2020-12-05 14:57

    Recently I've implemented such control. It contains two buttons (to scroll left and right) which switch their IsEnabled and Visibility states when it is necessary. Also it works perfectly with item selection: if you select a half-visible item, it will scroll to display it fully.

    It looks so:

    WPF Scrollable TabControl

    It isn't so much different from the default control, the scrolling is appeared automatically:

    <tab:ScrollableTabControl ItemsSource="{Binding Items}" 
        SelectedItem="{Binding SelectedItem, Mode=TwoWay}" 
        IsAddItemEnabled="False" 
        .../>
    

    I've written the article about this ScrollableTabControl class in my blog here.

    Source code you can find here: WpfScrollableTabControl.zip

    0 讨论(0)
提交回复
热议问题