问题描述
我正在WPF中动态创建Tabitem。我需要创建带有箭头的标签页眉,以在箭头单击时显示一组标签页眉,如下图所示。
例如如果我有10个标签,则最初应显示3个标签,然后单击下一步按钮,则应显示下3个标签。
我发现选项卡标题模板中的选项卡很有用,它可以将多行中的元素显示为每行或多或少相等。
选项卡控件的控件模板的代码如下
<Setter Property="Template">
<Setter.Value>
<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>
<Grid Grid.Column="0" Background="#f7f7f7">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDeFinitions>
<ColumnDeFinition></ColumnDeFinition>
<ColumnDeFinition Width="0"></ColumnDeFinition>
</Grid.ColumnDeFinitions>
<TabPanel x:Name="headerPanel" IsItemsHost="true" Margin="2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1" Grid.Column="0"/>
</Grid>
</Grid>
<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">
<Grid>
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</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,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"/>
</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"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
现在我得到的输出为
如何将多行显示为带有箭头的单行,以移动到下一行。任何代码示例都将有所帮助。
解决方法
基本上,您需要的是一个自定义滚动视图,该视图包装了用于标签页眉的自定义项目面板。
下面的scrollviewer模板将滚动条从项目而不是在其下方向左水平滚动-这有效地将其缩小为两个滚动按钮。另外请注意,PART_VerticalScrollBar
在此模板中永久折叠。
<ControlTemplate x:Key="ScrollViewerControlTemplate1" TargetType="{x:Type ScrollViewer}">
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
<ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="0" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset,Mode=OneWay,RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
<ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="Collapsed" Value="{Binding VerticalOffset,RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
</Grid>
</ControlTemplate>
现在,您可以在TabControl模板中,将TabPanel
替换为水平StackPanel
,并用上面的自定义模板包裹在ScrollViewer
中>
...
<ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto" Template="{DynamicResource ScrollViewerControlTemplate1}">
<StackPanel x:Name="headerPanel" Orientation="Horizontal" IsItemsHost="True" Grid.Column="0" Margin="2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
</ScrollViewer>
...
这应该大致产生所需的UI,并且它是配置所需行为的起点(例如,每次单击滚动箭头,您会左右滚动多少……)