I'm currently trying to implement my own stylized ComboBox in WPF. Everything is working fine, except for the scrollviewer. Simply put, the vertical scroll bar does nothing. Here is an image:
As you can see, the vertical scrollbar is scrolled all the way down, but it did not seem to trigger the effect of actually scrolling. I have 12 dummy items in the Combobox. I was reading online that the ScrollViewer style requires three things to work: ScrollContentPresenter, VerticalScrollBar, and HorizontalScrollBar. I have all three declared in my scrollviewer style, which is as follows:
<Style x:Key="VoidwalkerDarkScrollviewer" TargetType="{x:Type ScrollViewer}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="VerticalScrollBarVisibility" Value="Visible" />
<Setter Property="Padding" Value="4" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FFA3AEB9" />
<GradientStop Offset="0.375" Color="#FF8399A9" />
<GradientStop Offset="0.375" Color="#FF718597" />
<GradientStop Offset="1" Color="#FF617584" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ScrollContentPresenter
x:Name="ScrollContentPresenter"
Margin="{TemplateBinding Padding}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Cursor="{TemplateBinding Cursor}" />
<Rectangle
Grid.Row="1"
Grid.Column="1"
Fill="#FFE9EEF4" />
<ScrollBar
x:Name="VerticalScrollBar"
Grid.Row="0"
Grid.Column="1"
Width="18"
Margin="0,-1,-1,-1"
Background="Red"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableHeight}"
Minimum="0"
Orientation="Vertical"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{TemplateBinding VerticalOffset}" />
<ScrollBar
x:Name="HorizontalScrollBar"
Grid.Row="1"
Grid.Column="0"
Height="18"
Margin="-1,0,-1,-1"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableWidth}"
Minimum="0"
Orientation="Horizontal"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Value="{TemplateBinding HorizontalOffset}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here is my Combobox style (Omitting extras which are not relevant)
<Style x:Key="VoidwalkerDarkComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="MinWidth" Value="120" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton
Name="ToggleButton"
Grid.Column="2"
ClickMode="Press"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Template="{StaticResource ComboBoxToggleButton}" />
<ContentPresenter
Name="ContentSite"
Margin="3,3,23,3"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
IsHitTestVisible="False" />
<TextBox
x:Name="PART_EditableTextBox"
Margin="3,3,23,3"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="Transparent"
Focusable="True"
Foreground="#d0d0d0"
IsReadOnly="{TemplateBinding IsReadOnly}"
Style="{x:Null}"
Template="{StaticResource ComboBoxTextBox}"
Text="{TemplateBinding Text}"
Visibility="Visible" />
<Popup
Name="Popup"
AllowsTransparency="True"
Focusable="False"
IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Bottom"
PopupAnimation="Slide">
<Grid
Name="DropDown"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
SnapsToDevicePixels="True">
<Border
x:Name="DropDownBorder"
Background="#1b1b1c"
BorderBrush="#3f3f46"
BorderThickness="1" />
<ScrollViewer
Margin="4,6,4,6"
SnapsToDevicePixels="True"
Style="{DynamicResource VoidwalkerDarkScrollviewer}"><!-- IF I REMOVE THIS STYLE EVERYTHING WORKS FINE !-->
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="LightGray" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="0,0,4,4" />
<Setter TargetName="DropDownBorder" Property="Margin" Value="0" />
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false" />
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
<Setter TargetName="ContentSite" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As the comment in the style suggests, everything works fine if I simply remove the ScrollViewer style from the combobox...but I need it to complete my dark theme.
Does anyone know what I am missing to make this work?
rewriting ScrollViewer template to change ScrollBar color is an overkill.
ScrollBar is a part of ScrollViewer which is a part of ComboBox. Add a default ScrollBar style in ComboBox style Resources and change color via setter:
<Style TargetType="ComboBox">
<Style.Resources>
<Style TargetType="ScrollBar">
<Setter Property="Background" Value="Red"/>
</Style>
</Style.Resources>
</Style>
I figured it out. Just needed to dig a little deeper online. Here's some working XAML(Some of it may not be needed, but it's for full combobox styling) and a picture to show it)
<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Border
x:Name="Border"
Grid.ColumnSpan="2"
Background="#3f3f46"
BorderBrush="#3f3f46"
BorderThickness="1" />
<Border
Grid.Column="0"
Margin="1"
Background="#333337"
BorderBrush="#3f3f46"
BorderThickness="0,0,1,0" />
<Path
x:Name="Arrow"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"
Fill="#d0d0d0" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="LightGray" />
<Setter TargetName="Border" Property="BorderBrush" Value="Gray" />
<Setter Property="Foreground" Value="DarkGray" />
<Setter TargetName="Arrow" Property="Fill" Value="DarkGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
<ScrollViewer
x:Name="PART_ContentHost"
Background="{TemplateBinding Background}"
Focusable="False" />
</ControlTemplate>
<ControlTemplate x:Key="ScrollBackground" TargetType="RepeatButton">
<Border Background="Transparent" />
</ControlTemplate>
<Style x:Key="ScrollThumbStyle" TargetType="Thumb">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Rectangle
Width="13"
Fill="#7D7D7D"
RadiusX="5"
RadiusY="5" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ComboBox style -->
<Style x:Key="VoidwalkerDarkComboBox" TargetType="{x:Type ComboBox}">
<Style.Resources>
<Style TargetType="ScrollBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid Width="15">
<Border
Width="13"
HorizontalAlignment="Center"
Background="#33555555"
CornerRadius="5" />
<Track
Name="PART_Track"
Width="{TemplateBinding Width}"
HorizontalAlignment="Center"
IsDirectionReversed="true"
Maximum="{TemplateBinding Maximum}"
Minimum="{TemplateBinding Minimum}"
Value="{TemplateBinding Value}">
<Track.DecreaseRepeatButton>
<RepeatButton Command="ScrollBar.LineUpCommand" Template="{StaticResource ScrollBackground}" />
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="ScrollBar.LineDownCommand" Template="{StaticResource ScrollBackground}" />
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource ScrollThumbStyle}" />
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="MinWidth" Value="120" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton
Name="ToggleButton"
Grid.Column="2"
ClickMode="Press"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Template="{StaticResource ComboBoxToggleButton}" />
<ContentPresenter
Name="ContentSite"
Margin="3,3,23,3"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
IsHitTestVisible="False" />
<TextBox
x:Name="PART_EditableTextBox"
Margin="3,3,23,3"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="Transparent"
Focusable="True"
Foreground="#d0d0d0"
IsReadOnly="{TemplateBinding IsReadOnly}"
Style="{x:Null}"
Template="{StaticResource ComboBoxTextBox}"
Text="{TemplateBinding Text}"
Visibility="Visible" />
<Popup
Name="Popup"
AllowsTransparency="True"
Focusable="False"
IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Bottom"
PopupAnimation="Slide">
<Grid
Name="DropDown"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
SnapsToDevicePixels="True">
<Border
x:Name="DropDownBorder"
Background="#1b1b1c"
BorderBrush="#3f3f46"
BorderThickness="1" />
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="LightGray" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="0,0,4,4" />
<Setter TargetName="DropDownBorder" Property="Margin" Value="0" />
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false" />
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
<Setter TargetName="ContentSite" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My best guess is that originally overriding the ScrollViewer itself must have broke something internally...perhaps I left something out. I don't know. Either way, a solution/alternative is just to provide a style for the scrollbars themselves, and ignore the ScrollViewer altogether.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.