如何更改滚动 WPF TabControl 中 TabItems 的外观?
我有一个滚动 TabControl,使用 ScrollViewer 和 StackPanel (StackPanel 设置为 IsItemsHost="true")。首先,我正在使用最初概述的解决方案 - 使用 WPF 的 TabControl 创建滚动选项卡 。目前它的链接已损坏(编辑:我在这里的论坛中找到了他的代码的一个实例 - 如何防止 TabControl 执行多行操作?),所以这里是 TabControl 的 xaml(不需要任何进一步的代码):
<TabControl x:Name="TabControl2" Height="Auto" TabStripPlacement="Bottom" VerticalAlignment="Bottom" Template="{DynamicResource TabControlControlTemplate1}" IsSynchronizedWithCurrentItem="True">
<TabControl.Resources>
<Style x:Key="TabScrollerRepeatButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" Margin="1,0">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding ContentControl.Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="TabControlControlTemplate1" TargetType="{x:Type TabControl}">
<Grid x:Name="Grid" 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>
<Border Grid.Row="1" Grid.Column="0" x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,0,1,1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.DirectionalNavigation="Contained">
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Border Background="{TemplateBinding Background}" x:Name="Border1">
<ContentPresenter DataContext="{x:Null}" Margin="{TemplateBinding Padding}" x:Name="PART_SelectedContentHost" Content="{TemplateBinding SelectedContent}" ContentTemplate="{TemplateBinding SelectedContentTemplate}" ContentTemplateSelector="{TemplateBinding SelectedContentTemplateSelector}" ContentSource="SelectedContent"/>
</Border>
</Border>
</Border>
<ScrollViewer x:Name="HeaderPanel" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<ScrollViewer.Style>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Margin="0,0,0,0" Grid.Row="0" Grid.Column="0" x:Name="HeaderPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<RepeatButton Grid.Column="1" Content="<" Command="ScrollBar.LineLeftCommand" Style="{DynamicResource TabScrollerRepeatButtonStyle}" Visibility="{Binding Path=ComputedHorizontalScrollBarVisibility, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<ScrollContentPresenter Grid.Column="2" Content="{TemplateBinding ScrollViewer.Content}" />
<RepeatButton Grid.Column="3" Content=">" Command="ScrollBar.LineRightCommand" Style="{DynamicResource TabScrollerRepeatButtonStyle}" Visibility="{Binding Path=ComputedHorizontalScrollBarVisibility, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ScrollViewer.Style>
<StackPanel IsItemsHost="true" Orientation="Horizontal" Background="{x:Null}" KeyboardNavigation.TabIndex="1"/>
</ScrollViewer>
</Grid>
</ControlTemplate>
</TabControl.Resources>
<TabItem x:Name="TabItem1" Header="TabItem1"/>
<TabItem x:Name="TabItem2" Header="TabItem2"/>
</TabControl>
我如何调整每个 TabItem 的外观?例如,我想在 StackPanel 的帮助下在每个 TabItem 中放置一个 TextBox 和 TextBlock,以便我可以拥有可重命名的选项卡(根据需要折叠一个或另一个)。我可能还想在每个选项卡上添加一个关闭按钮。通常,我会使用类似以下的内容:
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Name="panel" Orientation="Horizontal">
<TextBox Name="editHeader" Text="{Binding Header}" MaxWidth="250"/>
<TextBlock Name="textHeader" Text="{Binding Header}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
..但这根本没有效果。任何想法将不胜感激。谢谢。
编辑:我仍在试图弄清楚这一点。该解决方案是否可能涉及 ContentPresenter 和/或 SelectedContentTemplate?
编辑2:(这不会为我的问题增加价值)我真的非常希望WPF 包含这种开箱即用的东西。我对 TabControl 的默认行为感到困惑,而且几年后没有可滚动的 TabControl (也没有简单的解决方案来实现)。
I have a scrolling TabControl, using a ScrollViewer and StackPanel (with the StackPanel set as IsItemsHost="true"). To begin with, I am working from a solution originally outlined here - Creating Scrolling Tabs Using WPF's TabControl . At the moment it has broken links (Edit: I have tracked down one instance of his code in a forum here - How to prevent TabControl from doing multi rows?), so here is the xaml for the TabControl (does not require any further code):
<TabControl x:Name="TabControl2" Height="Auto" TabStripPlacement="Bottom" VerticalAlignment="Bottom" Template="{DynamicResource TabControlControlTemplate1}" IsSynchronizedWithCurrentItem="True">
<TabControl.Resources>
<Style x:Key="TabScrollerRepeatButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" Margin="1,0">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding ContentControl.Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="TabControlControlTemplate1" TargetType="{x:Type TabControl}">
<Grid x:Name="Grid" 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>
<Border Grid.Row="1" Grid.Column="0" x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,0,1,1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local" KeyboardNavigation.DirectionalNavigation="Contained">
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Border Background="{TemplateBinding Background}" x:Name="Border1">
<ContentPresenter DataContext="{x:Null}" Margin="{TemplateBinding Padding}" x:Name="PART_SelectedContentHost" Content="{TemplateBinding SelectedContent}" ContentTemplate="{TemplateBinding SelectedContentTemplate}" ContentTemplateSelector="{TemplateBinding SelectedContentTemplateSelector}" ContentSource="SelectedContent"/>
</Border>
</Border>
</Border>
<ScrollViewer x:Name="HeaderPanel" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<ScrollViewer.Style>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Margin="0,0,0,0" Grid.Row="0" Grid.Column="0" x:Name="HeaderPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<RepeatButton Grid.Column="1" Content="<" Command="ScrollBar.LineLeftCommand" Style="{DynamicResource TabScrollerRepeatButtonStyle}" Visibility="{Binding Path=ComputedHorizontalScrollBarVisibility, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<ScrollContentPresenter Grid.Column="2" Content="{TemplateBinding ScrollViewer.Content}" />
<RepeatButton Grid.Column="3" Content=">" Command="ScrollBar.LineRightCommand" Style="{DynamicResource TabScrollerRepeatButtonStyle}" Visibility="{Binding Path=ComputedHorizontalScrollBarVisibility, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ScrollViewer.Style>
<StackPanel IsItemsHost="true" Orientation="Horizontal" Background="{x:Null}" KeyboardNavigation.TabIndex="1"/>
</ScrollViewer>
</Grid>
</ControlTemplate>
</TabControl.Resources>
<TabItem x:Name="TabItem1" Header="TabItem1"/>
<TabItem x:Name="TabItem2" Header="TabItem2"/>
</TabControl>
How might I adjust the appearance of each TabItem? For instance, I would like to place a TextBox and TextBlock inside each TabItem, with the help of a StackPanel, so that I can have renameable tabs (collapsing one or the other as appropriate). I might also want to add a close button on each tab. Ordinarily, I would use something like the following:
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Name="panel" Orientation="Horizontal">
<TextBox Name="editHeader" Text="{Binding Header}" MaxWidth="250"/>
<TextBlock Name="textHeader" Text="{Binding Header}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
.. but this is having no effect at all. Any ideas would be appreciated. Thanks.
Edit: I am still trying to figure this out. Is it possible that the solution could involve ContentPresenter and/or SelectedContentTemplate?
Edit 2: (this doesn't add value to my question) I really, really wish WPF included something of this sort out of the box. I am baffled by TabControl's default behavior, and by the fact that there is no scrollable TabControl (nor simple solution for attaining one) after some years.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
嘿猜测者。我也做过类似的事情,但我是基于这个系列的
http://www.blogs.intuidev.com/post/2010/post/2010/01/25/TabControlStyling_PartOne.aspx
使用的方法是简单地设置 tabitems 模板的样式。例如:
不幸的是,这种方法意味着您将必须完全重新定义选项卡项目的外观和行为方式。但提供的链接给出了如何实现这一目标的很好的例子。
希望有帮助。
Hey guesser. I've done something similar, I based mine off of this series though
http://www.blogs.intuidev.com/post/2010/post/2010/01/25/TabControlStyling_PartOne.aspx
The method used is to simply style the tabitems template. eg:
Unforunately this method means you will have to completely redefine the way the tab items look and behave. But the provided link gives good examples on how achieve this.
Hope it helps.
只是想一想,
您是否尝试过将文本块添加到 TabItem.Header 中?如果您这样做而不是模板,它可能会起作用。对我来说过去
Just a thought,
have you tried just adding the text block to the TabItem.Header? If you do this instead of a template it might work. Has for me in the past
我想我已经明白了(尽管仍然有点交叉手指——我还没有处理用于重命名的 TextBlock 与 TextBox 的可见性)。
它与 Val 的解决方案类似,我在 TabControl.Resources 的 TabItem 上工作,但相关的属性是 HeaderTemplate,我只是覆盖 DataTemplate 中的 ContentPresenter。 (避免替换/破坏 TabControl 免费提供的许多良好行为的措施)
我有点像 WPF 新手,所以这基本上是我通过 Google 搜索找到的内容进行持续实验的结果。对于那些感兴趣的人,这个链接(在 StackOverflow 上)最终对我帮助最大 - WPF TabItem 标题样式
I think I've got it (though still crossing fingers a bit -- I haven't yet dealt with Visibility of the TextBlock vs TextBox for renaming).
It is similar to Val's solution in that I'm working in TabControl.Resources on its TabItem, but the Property concerned is HeaderTemplate and I just override the ContentPresenter in a DataTemplate. (measures to avoid replacing\destroying a lot of good behavior that comes for free with the TabControl)
I'm somewhat of a WPF newb, so this is basically a result of persistent experimentation with what I could find Googling. For those interested, this link (on StackOverflow) helped me most in the end - WPF TabItem Header Styling