设置 WPF ScrollViewer 的样式,使其看起来像 VS2010 选项卡滚动条
我正在使用 AvalonDock 开发一个供我们的开发人员和 QA 内部使用的工具。我正在开发主题中提供的 VS2010 样式的自定义版本。这种风格的功能不够像 VS2010 那样让我满意。我已经完成了几乎所有的颜色和图像更改,我只是注意到当选项卡数量超出标题区域的容纳范围时,DocumentPane 中的选项卡不会像 VS2010 那样滚动。
由于我的项目中有完整的样式,因此我找到了应用样式的区域。我在 ad:DocumentTabPanel 周围放置了一个 ScrollViewer,认为我可以以某种方式重新设置水平滚动条的样式,以便选项卡的左侧和右侧都有一个箭头。
这可能吗?
这是我基本修改后的样式,但未对滚动查看器进行任何修改:
<Style x:Key="{x:Type ad:DocumentPane}" TargetType="{x:Type ad:DocumentPane}">
<Setter Property="Background" Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DefaultBackgroundBrush}}}"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ad:DocumentPane}" >
<ControlTemplate.Resources>
<ContextMenu x:Key="DocumentsListMenu" StaysOpen="True" />
</ControlTemplate.Resources>
<Border
Background="{TemplateBinding Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="PART_Header"
Grid.Row="0"
Focusable="False"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="18"/>
</Grid.ColumnDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" CanContentScroll="True">
<ad:DocumentTabPanel
x:Name="paneTabsPanel"
Panel.ZIndex ="1"
IsItemsHost="True"
TabItemStyle="{StaticResource CustomDocumentTabItemStyle}"/>
</ScrollViewer>
<Button x:Name="PART_ShowContextMenuButton"
Grid.Column="2"
Width="15" Height="15"
Style="{StaticResource PaneHeaderCommandStyle}">
<Image x:Name="ShowContextMenuIcon" Source="pack://application:,,,/Images/Dev2010/PinMenu.png" Width="13" Height="13" Stretch="None"/>
</Button>
</Grid>
</Border>
<Grid Grid.Row="1">
<Border
x:Name="topBorder"
Height="4"
Background="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorder}}}"
CornerRadius="2,2,0,0"
VerticalAlignment="Top"
HorizontalAlignment="Stretch"
>
</Border>
<Border
x:Name="bottomBorder"
Height="4"
Background="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorder}}}"
CornerRadius="0,0,2,2"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
>
</Border>
<ContentPresenter
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.Content}"
Margin="0,4,0,4"
KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="1"
/>
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</Trigger>
<Trigger Property="ShowHeader" Value="False">
<Setter Property="Visibility" Value="Collapsed" TargetName="PART_Header" />
</Trigger>
<!--<DataTrigger Binding="{Binding Path=IsMainDocumentPane, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Source" Value="pack://application:,,,/Images/Dev2010/PinDockMenu.png" TargetName="ShowContextMenuIcon"/>
</DataTrigger>-->
<Trigger Property="ContainsActiveDocument" Value="True">
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelected}}}"
TargetName="topBorder"/>
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelected}}}"
TargetName="bottomBorder"/>
</Trigger>
<Trigger Property="ContainsActiveContent" Value="True">
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelectedActivated}}}"
TargetName="topBorder"/>
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelectedActivated}}}"
TargetName="bottomBorder"/>
</Trigger>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0" To="1" Duration="0:0:0.200" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'm using AvalonDock to develop a tool for internal use by our developers and QA. I am working on a custom version of the VS2010 style that is provided in the Themes. The style just didn't function enough like VS2010 for me to be happy with it. I've made almost all the color and image changes and I just noticed that the tabs in the DocumentPane do not scroll like VS2010 when there are more tabs than can fit in the header area.
Since I have the complete style in my project I found the area where the styles are applied. I placed a ScrollViewer around the ad:DocumentTabPanel thinking I could somehow restyle the horizontal scrollbar so that there would be an arrow on the left and on the right of the tabs.
Is this possible?
Here is the style after my base modifications but without any modification to the scrollviewer:
<Style x:Key="{x:Type ad:DocumentPane}" TargetType="{x:Type ad:DocumentPane}">
<Setter Property="Background" Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DefaultBackgroundBrush}}}"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ad:DocumentPane}" >
<ControlTemplate.Resources>
<ContextMenu x:Key="DocumentsListMenu" StaysOpen="True" />
</ControlTemplate.Resources>
<Border
Background="{TemplateBinding Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="PART_Header"
Grid.Row="0"
Focusable="False"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="18"/>
</Grid.ColumnDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" CanContentScroll="True">
<ad:DocumentTabPanel
x:Name="paneTabsPanel"
Panel.ZIndex ="1"
IsItemsHost="True"
TabItemStyle="{StaticResource CustomDocumentTabItemStyle}"/>
</ScrollViewer>
<Button x:Name="PART_ShowContextMenuButton"
Grid.Column="2"
Width="15" Height="15"
Style="{StaticResource PaneHeaderCommandStyle}">
<Image x:Name="ShowContextMenuIcon" Source="pack://application:,,,/Images/Dev2010/PinMenu.png" Width="13" Height="13" Stretch="None"/>
</Button>
</Grid>
</Border>
<Grid Grid.Row="1">
<Border
x:Name="topBorder"
Height="4"
Background="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorder}}}"
CornerRadius="2,2,0,0"
VerticalAlignment="Top"
HorizontalAlignment="Stretch"
>
</Border>
<Border
x:Name="bottomBorder"
Height="4"
Background="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorder}}}"
CornerRadius="0,0,2,2"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
>
</Border>
<ContentPresenter
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.Content}"
Margin="0,4,0,4"
KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="1"
/>
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</Trigger>
<Trigger Property="ShowHeader" Value="False">
<Setter Property="Visibility" Value="Collapsed" TargetName="PART_Header" />
</Trigger>
<!--<DataTrigger Binding="{Binding Path=IsMainDocumentPane, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Source" Value="pack://application:,,,/Images/Dev2010/PinDockMenu.png" TargetName="ShowContextMenuIcon"/>
</DataTrigger>-->
<Trigger Property="ContainsActiveDocument" Value="True">
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelected}}}"
TargetName="topBorder"/>
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelected}}}"
TargetName="bottomBorder"/>
</Trigger>
<Trigger Property="ContainsActiveContent" Value="True">
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelectedActivated}}}"
TargetName="topBorder"/>
<Setter Property="Background"
Value="{DynamicResource {ComponentResourceKey {x:Type ad:DockingManager}, {x:Static ad:AvalonDockBrushes.DocumentHeaderBorderSelectedActivated}}}"
TargetName="bottomBorder"/>
</Trigger>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0" To="1" Duration="0:0:0.200" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我过去做过类似的事情,发现最简单的方法是隐藏 ScrollViewer 的 ScrollBar,并在按下两个 RepeatButton 时手动滚动内容。
我最初开始使用的代码可以在此处找到,但基本思想是覆盖 ScrollViewer 的模板,使其看起来像这样:
I did something like this in the past, and found it easiest to hide the ScrollViewer's ScrollBar, and manually scroll the content when two RepeatButtons are pressed.
The code I originally started with can be found here, but the basic idea is to overwrite the ScrollViewer's template to look something like this: