简体   繁体   中英

WPF Styled Scrollviewer Not Scrolling

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM