WPF自定义滚动条(含windows和apple两种风格)

测试结构

    <Grid>
        <ListView  VerticalAlignment="Top" HorizontalAlignment="Stretch">
            <ListViewItem>
                <TextBlock Text="xxxx1"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx2"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx3"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx4"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx5"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx6"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx7"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx8"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx9"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx10"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx11"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx12"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx13"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx14"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx15"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx16"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx17"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx18"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx19"/>
            </ListViewItem>
            <ListViewItem>
                <TextBlock Text="xxxx20"/>
            </ListViewItem>
        </ListView>
    </Grid>

Windows 风格

file

<Style x:Key="ScrollBarLineButton"
       TargetType="{x:Type RepeatButton}">
  <Setter Property="SnapsToDevicePixels"
          Value="True" />
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Setter Property="Focusable"
          Value="false" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type RepeatButton}">
        <Border x:Name="Border"
                Margin="1"
                CornerRadius="2"
                BorderThickness="1">
          <Border.BorderBrush>
            <LinearGradientBrush StartPoint="0,0"
                                 EndPoint="0,1">
              <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                  <GradientStop Color="{DynamicResource BorderMediumColor}"
                                Offset="0.0" />
                  <GradientStop Color="{DynamicResource BorderDarkColor}"
                                Offset="1.0" />
                </GradientStopCollection>
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
          </Border.BorderBrush>
          <Border.Background>
            <LinearGradientBrush StartPoint="0,0"
                                 EndPoint="0,1">
              <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                  <GradientStop Color="{DynamicResource ControlLightColor}"/>
                  <GradientStop Color="{DynamicResource ControlMediumColor}"
                                Offset="1.0" />
                </GradientStopCollection>
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
          </Border.Background>
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal" />
              <VisualState x:Name="MouseOver" />
              <VisualState x:Name="Pressed">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="(Panel.Background).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource ControlPressedColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ColorAnimationUsingKeyFrames Storyboard.TargetName="Arrow"
                                                Storyboard.TargetProperty="(Shape.Fill).
                    (SolidColorBrush.Color)">
                    <EasingColorKeyFrame KeyTime="0"
                                         Value="{StaticResource DisabledForegroundColor}" />
                  </ColorAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
          </VisualStateManager.VisualStateGroups>
          <Path x:Name="Arrow"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Data="{Binding Content, 
            RelativeSource={RelativeSource TemplatedParent}}" >
              <Path.Fill>
                  <SolidColorBrush Color="{DynamicResource GlyphColor}"/>
              </Path.Fill>
          </Path>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="ScrollBarPageButton"
       TargetType="{x:Type RepeatButton}">
  <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="{x:Type RepeatButton}">
        <Border Background="Transparent" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="ScrollBarThumb"
       TargetType="{x:Type 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="{x:Type Thumb}">
        <Border CornerRadius="2"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="1" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<ControlTemplate x:Key="VerticalScrollBar"
                 TargetType="{x:Type ScrollBar}">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition MaxHeight="18" />
      <RowDefinition Height="0.00001*" />
      <RowDefinition MaxHeight="18" />
    </Grid.RowDefinitions>
    <Border Grid.RowSpan="3"
            CornerRadius="2"
            Background="#F0F0F0" />
    <RepeatButton Grid.Row="0"
                  Style="{StaticResource ScrollBarLineButton}"
                  Height="18"
                  Command="ScrollBar.LineUpCommand"
                  Content="M 0 4 L 8 4 L 4 0 Z" />
    <Track x:Name="PART_Track"
           Grid.Row="1"
           IsDirectionReversed="true">
      <Track.DecreaseRepeatButton>
        <RepeatButton Style="{StaticResource ScrollBarPageButton}"
                      Command="ScrollBar.PageUpCommand" />
      </Track.DecreaseRepeatButton>
      <Track.Thumb>
        <Thumb Style="{StaticResource ScrollBarThumb}"
               Margin="1,0,1,0">
          <Thumb.BorderBrush>

            <LinearGradientBrush StartPoint="0,0"
                                 EndPoint="1,0">
              <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                  <GradientStop Color="{DynamicResource BorderLightColor}"
                                Offset="0.0" />
                  <GradientStop Color="{DynamicResource BorderDarkColor}"
                                Offset="1.0" />
                </GradientStopCollection>
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>

          </Thumb.BorderBrush>
          <Thumb.Background>

            <LinearGradientBrush StartPoint="0,0"
                                 EndPoint="1,0">
              <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                  <GradientStop Color="{DynamicResource ControlLightColor}"
                                Offset="0.0" />
                  <GradientStop Color="{DynamicResource ControlMediumColor}"
                                Offset="1.0" />
                </GradientStopCollection>
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>

          </Thumb.Background>
        </Thumb>
      </Track.Thumb>
      <Track.IncreaseRepeatButton>
        <RepeatButton Style="{StaticResource ScrollBarPageButton}"
                      Command="ScrollBar.PageDownCommand" />
      </Track.IncreaseRepeatButton>
    </Track>
    <RepeatButton Grid.Row="2"
                  Style="{StaticResource ScrollBarLineButton}"
                  Height="18"
                  Command="ScrollBar.LineDownCommand"
                  Content="M 0 0 L 4 4 L 8 0 Z" />
  </Grid>
</ControlTemplate>

<ControlTemplate x:Key="HorizontalScrollBar"
                 TargetType="{x:Type ScrollBar}">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition MaxWidth="18" />
      <ColumnDefinition Width="0.00001*" />
      <ColumnDefinition MaxWidth="18" />
    </Grid.ColumnDefinitions>
    <Border Grid.ColumnSpan="3"
            CornerRadius="2"
            Background="#F0F0F0" />
    <RepeatButton Grid.Column="0"
                  Style="{StaticResource ScrollBarLineButton}"
                  Width="18"
                  Command="ScrollBar.LineLeftCommand"
                  Content="M 4 0 L 4 8 L 0 4 Z" />
    <Track x:Name="PART_Track"
           Grid.Column="1"
           IsDirectionReversed="False">
      <Track.DecreaseRepeatButton>
        <RepeatButton Style="{StaticResource ScrollBarPageButton}"
                      Command="ScrollBar.PageLeftCommand" />
      </Track.DecreaseRepeatButton>
      <Track.Thumb>
        <Thumb Style="{StaticResource ScrollBarThumb}"
               Margin="0,1,0,1">

          <Thumb.BorderBrush>

            <LinearGradientBrush StartPoint="0,0"
                                 EndPoint="1,0">
              <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                  <GradientStop Color="{DynamicResource BorderLightColor}"
                                Offset="0.0" />
                  <GradientStop Color="{DynamicResource BorderDarkColor}"
                                Offset="1.0" />
                </GradientStopCollection>
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>

          </Thumb.BorderBrush>
          <Thumb.Background>

            <LinearGradientBrush StartPoint="0,0"
                                 EndPoint="0,1">
              <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                  <GradientStop Color="{DynamicResource ControlLightColor}"
                                Offset="0.0" />
                  <GradientStop Color="{DynamicResource ControlMediumColor}"
                                Offset="1.0" />
                </GradientStopCollection>
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>

          </Thumb.Background>
        </Thumb>
      </Track.Thumb>
      <Track.IncreaseRepeatButton>
        <RepeatButton Style="{StaticResource ScrollBarPageButton}"
                      Command="ScrollBar.PageRightCommand" />
      </Track.IncreaseRepeatButton>
    </Track>
    <RepeatButton Grid.Column="2"
                  Style="{StaticResource ScrollBarLineButton}"
                  Width="18"
                  Command="ScrollBar.LineRightCommand"
                  Content="M 0 0 L 4 4 L 0 8 Z" />
  </Grid>
</ControlTemplate>

<Style x:Key="{x:Type ScrollBar}"
       TargetType="{x:Type ScrollBar}">
  <Setter Property="SnapsToDevicePixels"
          Value="True" />
  <Setter Property="OverridesDefaultStyle"
          Value="true" />
  <Style.Triggers>
    <Trigger Property="Orientation"
             Value="Horizontal">
      <Setter Property="Width"
              Value="Auto" />
      <Setter Property="Height"
              Value="18" />
      <Setter Property="Template"
              Value="{StaticResource HorizontalScrollBar}" />
    </Trigger>
    <Trigger Property="Orientation"
             Value="Vertical">
      <Setter Property="Width"
              Value="18" />
      <Setter Property="Height"
              Value="Auto" />
      <Setter Property="Template"
              Value="{StaticResource VerticalScrollBar}" />
    </Trigger>
  </Style.Triggers>
</Style>

需要的资源

<!--Control colors.-->
<Color x:Key="WindowColor">#FFE8EDF9</Color>
<Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
<Color x:Key="ContentAreaColorDark">#FF7381F9</Color>

<Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
<Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
<Color x:Key="DisabledForegroundColor">#FF888888</Color>

<Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
<Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>

<Color x:Key="ControlLightColor">White</Color>
<Color x:Key="ControlMediumColor">#FF7381F9</Color>
<Color x:Key="ControlDarkColor">#FF211AA9</Color>

<Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
<Color x:Key="ControlPressedColor">#FF211AA9</Color>

<Color x:Key="GlyphColor">#FF444444</Color>
<Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>

<!--Border colors-->
<Color x:Key="BorderLightColor">#FFCCCCCC</Color>
<Color x:Key="BorderMediumColor">#FF888888</Color>
<Color x:Key="BorderDarkColor">#FF444444</Color>

<Color x:Key="PressedBorderLightColor">#FF888888</Color>
<Color x:Key="PressedBorderDarkColor">#FF444444</Color>

<Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
<Color x:Key="DisabledBorderDarkColor">#FF888888</Color>

<Color x:Key="DefaultBorderBrushDarkColor">Black</Color>

<!--Control-specific resources.-->
<Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
<Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
<Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>

<Color x:Key="NavButtonFrameColor">#FF3843C4</Color>

<LinearGradientBrush x:Key="MenuPopupBrush"
                     EndPoint="0.5,1"
                     StartPoint="0.5,0">
  <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="0" />
  <GradientStop Color="{DynamicResource ControlMediumColor}"
                Offset="0.5" />
  <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
                     StartPoint="0,0"
                     EndPoint="1,0">
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Color="#000000FF"
                    Offset="0" />
      <GradientStop Color="#600000FF"
                    Offset="0.4" />
      <GradientStop Color="#600000FF"
                    Offset="0.6" />
      <GradientStop Color="#000000FF"
                    Offset="1" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Apple风格

file

<!--Scrollbar Thumbs-->
<Style x:Key="ScrollThumbs" TargetType="{x:Type Thumb}">
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type Thumb}">
            <Grid x:Name="Grid">
                <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Fill="Transparent" />
                <Border x:Name="Rectangle1" CornerRadius="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Background="{TemplateBinding Background}" />
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="Tag" Value="Horizontal">
                    <Setter TargetName="Rectangle1" Property="Width" Value="Auto" />
                    <Setter TargetName="Rectangle1" Property="Height" Value="7" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>
<!--ScrollBars-->
<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
<Setter Property="Stylus.IsFlicksEnabled" Value="false" />
<Setter Property="Foreground" Value="#8C8C8C" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Width" Value="8" />
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type ScrollBar}">
            <Grid x:Name="GridRoot" Width="8" Background="{TemplateBinding Background}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="0.00001*" />
                </Grid.RowDefinitions>
                <Track x:Name="PART_Track" Grid.Row="0" IsDirectionReversed="true" Focusable="false">
                    <Track.Thumb>
                        <Thumb x:Name="Thumb" Background="{TemplateBinding Foreground}" Style="{DynamicResource ScrollThumbs}" />
                    </Track.Thumb>
                    <Track.IncreaseRepeatButton>
                        <RepeatButton x:Name="PageUp" Command="ScrollBar.PageDownCommand" Opacity="0" Focusable="false" />
                    </Track.IncreaseRepeatButton>
                    <Track.DecreaseRepeatButton>
                        <RepeatButton x:Name="PageDown" Command="ScrollBar.PageUpCommand" Opacity="0" Focusable="false" />
                    </Track.DecreaseRepeatButton>
                </Track>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger SourceName="Thumb" Property="IsMouseOver" Value="true">
                    <Setter Value="{DynamicResource ButtonSelectBrush}" TargetName="Thumb" Property="Background" />
                </Trigger>
                <Trigger SourceName="Thumb" Property="IsDragging" Value="true">
                    <Setter Value="{DynamicResource DarkBrush}" TargetName="Thumb" Property="Background" />
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter TargetName="Thumb" Property="Visibility" Value="Collapsed" />
                </Trigger>
                <Trigger Property="Orientation" Value="Horizontal">
                    <Setter TargetName="GridRoot" Property="LayoutTransform">
                        <Setter.Value>
                            <RotateTransform Angle="-90" />
                        </Setter.Value>
                    </Setter>
                    <Setter TargetName="PART_Track" Property="LayoutTransform">
                        <Setter.Value>
                            <RotateTransform Angle="-90" />
                        </Setter.Value>
                    </Setter>
                    <Setter Property="Width" Value="Auto" />
                    <Setter Property="Height" Value="8" />
                    <Setter TargetName="Thumb" Property="Tag" Value="Horizontal" />
                    <Setter TargetName="PageDown" Property="Command" Value="ScrollBar.PageLeftCommand" />
                    <Setter TargetName="PageUp" Property="Command" Value="ScrollBar.PageRightCommand" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

参考