Skip to content

Instantly share code, notes, and snippets.

@maxkatz6
Created April 17, 2022 03:00
Show Gist options
  • Save maxkatz6/c50cb80c3a1402518a71f2bf5fe07cba to your computer and use it in GitHub Desktop.
Save maxkatz6/c50cb80c3a1402518a71f2bf5fe07cba to your computer and use it in GitHub Desktop.
horizontalScroller
<TabControl Classes="horizontalScroller" />
<Style Selector="ScrollViewer.horizontalScroller">
<Setter Property="Template">
<ControlTemplate>
<DockPanel>
<RepeatButton x:Name="ScrollLeftButton"
DockPanel.Dock="Left"
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
Command="{Binding PageLeft, RelativeSource={RelativeSource TemplatedParent}}">
<RepeatButton.IsVisible>
<MultiBinding Converter="{x:Static avaConv:MenuScrollingVisibilityConverter.Instance}"
ConverterParameter="0">
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="HorizontalScrollBarVisibility" />
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="Offset.X" />
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="Extent.Width" />
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="Viewport.Width" />
</MultiBinding>
</RepeatButton.IsVisible>
<Path VerticalAlignment="Center"
HorizontalAlignment="Center"
Fill="{Binding #ScrollLeftButton.Foreground}"
Data="M0.222099 4.6098L4.67223 0.159755C4.77515 0.0567475 4.91255 0 5.05905 0C5.20555 0 5.34295 0.0567475 5.44588 0.159755L5.7736 0.487394C5.98685 0.700889 5.98685 1.04788 5.7736 1.26105L2.03672 4.99793L5.77775 8.73895C5.88067 8.84196 5.9375 8.97928 5.9375 9.1257C5.9375 9.27228 5.88067 9.4096 5.77775 9.51269L5.45002 9.84025C5.34702 9.94325 5.2097 10 5.0632 10C4.9167 10 4.7793 9.94325 4.67637 9.84025L0.222099 5.38614C0.118929 5.2828 0.062263 5.14484 0.0625882 4.99817C0.062263 4.85094 0.118929 4.71305 0.222099 4.6098Z"
Width="6"
Height="10" />
</RepeatButton>
<RepeatButton x:Name="ScrollRightButton"
DockPanel.Dock="Right"
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
Command="{Binding PageRight, RelativeSource={RelativeSource TemplatedParent}}">
<RepeatButton.IsVisible>
<MultiBinding Converter="{x:Static avaConv:MenuScrollingVisibilityConverter.Instance}"
ConverterParameter="100">
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="HorizontalScrollBarVisibility" />
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="Offset.X" />
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="Extent.Width" />
<Binding RelativeSource="{RelativeSource TemplatedParent}"
Path="Viewport.Width" />
</MultiBinding>
</RepeatButton.IsVisible>
<Path VerticalAlignment="Center"
HorizontalAlignment="Center"
Fill="{Binding #ScrollRightButton.Foreground}"
Data="M5.7779 4.6098L1.32777 0.159755C1.22485 0.0567475 1.08745 0 0.940948 0C0.794445 0 0.657048 0.0567475 0.554122 0.159755L0.226401 0.487394C0.0131509 0.700889 0.0131509 1.04788 0.226401 1.26105L3.96328 4.99793L0.222255 8.73895C0.119329 8.84196 0.0625 8.97928 0.0625 9.1257C0.0625 9.27228 0.119329 9.4096 0.222255 9.51269L0.549976 9.84025C0.652983 9.94325 0.790299 10 0.936802 10C1.0833 10 1.2207 9.94325 1.32363 9.84025L5.7779 5.38614C5.88107 5.2828 5.93774 5.14484 5.93741 4.99817C5.93774 4.85094 5.88107 4.71305 5.7779 4.6098Z"
Width="6"
Height="10" />
</RepeatButton>
<ScrollContentPresenter Name="PART_ContentPresenter"
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}"
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}"
Content="{TemplateBinding Content}"
Extent="{TemplateBinding Extent, Mode=TwoWay}"
Margin="{TemplateBinding Padding}"
Offset="{TemplateBinding Offset, Mode=TwoWay}"
Viewport="{TemplateBinding Viewport, Mode=TwoWay}" />
</DockPanel>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="ScrollViewer.horizontalScroller /template/ RepeatButton">
<Setter Property="Width" Value="24" />
<Setter Property="Height" Value="24" />
<Setter Property="Padding" Value="0" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="RenderTransform" Value="{x:Null}" />
</Style>
<Style Selector="TabControl.horizontalScroller">
<Setter Property="Template">
<ControlTemplate>
<Border Margin="{TemplateBinding Margin}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}">
<DockPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled"
Padding="6,0"
Classes="horizontalScroller"
DockPanel.Dock="{TemplateBinding TabStripPlacement}">
<ItemsPresenter Name="PART_ItemsPresenter"
VirtualizationMode="Simple"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"
ItemTemplate="{TemplateBinding ItemTemplate}" />
</ScrollViewer>
<ContentPresenter Name="PART_SelectedContentHost"
Margin="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding SelectedContent}"
ContentTemplate="{TemplateBinding SelectedContentTemplate}" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter>
</Style>
@pyking-wang
Copy link

I am a beginner in ava. May I know what avaConv represents? thanks.

@afluegge
Copy link

afluegge commented Feb 26, 2024

I am trying to use your gist but run into trouble. I adjusted your code as follows:

<Styles xmlns="https://github.com/avaloniaui"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:avaConv="using:Avalonia.Controls.Converters">
   
   <Style Selector="ScrollViewer.horizontalScroller">
       <Setter Property="Template">
           <ControlTemplate>
               <DockPanel>
                   <RepeatButton x:Name="ScrollLeftButton"
                                 DockPanel.Dock="Left"
                                 Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
                                 Command="{Binding PageLeft, RelativeSource={RelativeSource TemplatedParent}}">
                       <RepeatButton.IsVisible>
                           <MultiBinding Converter="{x:Static avaConv:MenuScrollingVisibilityConverter.Instance}"
                                         ConverterParameter="0">
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="HorizontalScrollBarVisibility" />
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="Offset.X" />
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="Extent.Width" />
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="Viewport.Width" />
                           </MultiBinding>
                       </RepeatButton.IsVisible>
                       <Path VerticalAlignment="Center"
                             HorizontalAlignment="Center"
                             Fill="{Binding #ScrollLeftButton.Foreground}"
                             Data="M0.222099 4.6098L4.67223 0.159755C4.77515 0.0567475 4.91255 0 5.05905 0C5.20555 0 5.34295 0.0567475 5.44588 0.159755L5.7736 0.487394C5.98685 0.700889 5.98685 1.04788 5.7736 1.26105L2.03672 4.99793L5.77775 8.73895C5.88067 8.84196 5.9375 8.97928 5.9375 9.1257C5.9375 9.27228 5.88067 9.4096 5.77775 9.51269L5.45002 9.84025C5.34702 9.94325 5.2097 10 5.0632 10C4.9167 10 4.7793 9.94325 4.67637 9.84025L0.222099 5.38614C0.118929 5.2828 0.062263 5.14484 0.0625882 4.99817C0.062263 4.85094 0.118929 4.71305 0.222099 4.6098Z"
                             Width="6"
                             Height="10" />
                   </RepeatButton>
                   <RepeatButton x:Name="ScrollRightButton"
                                 DockPanel.Dock="Right"
                                 Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
                                 Command="{Binding PageRight, RelativeSource={RelativeSource TemplatedParent}}">
                       <RepeatButton.IsVisible>
                           <MultiBinding Converter="{x:Static avaConv:MenuScrollingVisibilityConverter.Instance}"
                                         ConverterParameter="100">
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="HorizontalScrollBarVisibility" />
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="Offset.X" />
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="Extent.Width" />
                               <Binding RelativeSource="{RelativeSource TemplatedParent}"
                                        Path="Viewport.Width" />
                           </MultiBinding>
                       </RepeatButton.IsVisible>
                       <Path VerticalAlignment="Center"
                             HorizontalAlignment="Center"
                             Fill="{Binding #ScrollRightButton.Foreground}"
                             Data="M5.7779 4.6098L1.32777 0.159755C1.22485 0.0567475 1.08745 0 0.940948 0C0.794445 0 0.657048 0.0567475 0.554122 0.159755L0.226401 0.487394C0.0131509 0.700889 0.0131509 1.04788 0.226401 1.26105L3.96328 4.99793L0.222255 8.73895C0.119329 8.84196 0.0625 8.97928 0.0625 9.1257C0.0625 9.27228 0.119329 9.4096 0.222255 9.51269L0.549976 9.84025C0.652983 9.94325 0.790299 10 0.936802 10C1.0833 10 1.2207 9.94325 1.32363 9.84025L5.7779 5.38614C5.88107 5.2828 5.93774 5.14484 5.93741 4.99817C5.93774 4.85094 5.88107 4.71305 5.7779 4.6098Z"
                             Width="6"
                             Height="10" />
                   </RepeatButton>
                   <ScrollContentPresenter Name="PART_ContentPresenter"
                                           CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}"
                                           CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}"
                                           Content="{TemplateBinding Content}"
                                           Extent="{TemplateBinding Extent, Mode=TwoWay}"
                                           Margin="{TemplateBinding Padding}"
                                           Offset="{TemplateBinding Offset, Mode=TwoWay}"
                                           Viewport="{TemplateBinding Viewport, Mode=TwoWay}" />
               </DockPanel>
           </ControlTemplate>
       </Setter>
   </Style>
   <Style Selector="ScrollViewer.horizontalScroller /template/ RepeatButton">
       <Setter Property="Width" Value="24" />
       <Setter Property="Height" Value="24" />
       <Setter Property="Padding" Value="0" />
       <Setter Property="BorderThickness" Value="0" />
       <Setter Property="HorizontalAlignment" Value="Stretch" />
       <Setter Property="HorizontalContentAlignment" Value="Center" />
       <Setter Property="RenderTransform" Value="{x:Null}" />
   </Style>

   <Style Selector="TabControl.horizontalScroller">
       <Setter Property="Template">
           <ControlTemplate>
               <Border Margin="{TemplateBinding Margin}"
                       BorderBrush="{TemplateBinding BorderBrush}"
                       BorderThickness="{TemplateBinding BorderThickness}"
                       Background="{TemplateBinding Background}"
                       HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                       VerticalAlignment="{TemplateBinding VerticalAlignment}">
                   <DockPanel>
                       <ScrollViewer HorizontalScrollBarVisibility="Auto"
                                     VerticalScrollBarVisibility="Disabled"
                                     Padding="6,0"
                                     Classes="horizontalScroller"
                                     DockPanel.Dock="{TemplateBinding TabStripPlacement}">
                           <ItemsPresenter Name="PART_ItemsPresenter"
                                           VirtualizationMode="Simple"
                                           Items="{TemplateBinding Items}"
                                           ItemsPanel="{TemplateBinding ItemsPanel}"
                                           ItemTemplate="{TemplateBinding ItemTemplate}" />
                       </ScrollViewer>
                       <ContentPresenter Name="PART_SelectedContentHost"
                                         Margin="{TemplateBinding Padding}"
                                         HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                         VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                         Content="{TemplateBinding SelectedContent}"
                                         ContentTemplate="{TemplateBinding SelectedContentTemplate}" />
                   </DockPanel>
               </Border>
           </ControlTemplate>
       </Setter>
   </Style>
</Styles>

I am left with 5 Errors:

  1. Line 58: 'CanHorizontallyScroll' is not accessible
  2. Line 59: 'CanVerticallyScroll' is not accessible
  3. Line 95: Unable to resolve symbol 'VirtualizationMode'
  4. Line 96: Unable to resolve symbol 'Items'
  5. Line 98: Unable to resolve symbol 'ItemTemplate'

I am using the latest Avalonia release, which is currently "11.0.9". Could it be that your gist is not compatible with this version?

Would it be possible to provide an adjusted version that is compatible with the latest version?

Many thanks in advance!

@derekantrican
Copy link

derekantrican commented Jul 24, 2024

@maxkatz6 I came across this while also trying to achieve a similar tab control behavior to WinForms (excessive tabs turn into a horizontal scroll rather than wrapping back around). I'm also encountering similar "Unable to resolve symbol" errors as @afluegge (at the end of their comment). Mind giving us a hint?

@maxkatz6
Copy link
Author

@derekantrican yea, this code was written for 0.10.
It needs to be rebased on default styles of 11.0/11.1

@derekantrican
Copy link

Actually I found this answer that works and is pretty close to what I want: AvaloniaUI/Avalonia#11896 (reply in thread)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment