burst2flame
Topic Author
Posts: 26
Joined: 11 Mar 2024, 18:04

Can't get pixel scrolling to work with a ScrollViewer

01 Oct 2024, 22:30

The scroll viewer works but it weirdly hides the full element at a time. I have "CanContentScroll" Set to false and VirtualizingStackPanel.ScrollUnit="Pixel" set on the grid, but it doesn't seem to work.
Screenshot 2024-10-01 132941.png
I also have this warning but I'm not sure why:

[NOESIS] Virtualization disabled: available viewport size is Infinite
UnityEngine.Debug:LogWarning (object,UnityEngine.Object)
NoesisUnity:UnityLog (int,string) (at ./Noesis/Runtime/NoesisUnity.cs:366)
Noesis.View:SetSize (int,int) (at ./Noesis/Runtime/API/Core/View.cs:65)
NoesisView:UpdateSize () (at ./Noesis/Runtime/NoesisView.cs:1383)
NoesisView:UpdateInternal () (at ./Noesis/Runtime/NoesisView.cs:1501)
NoesisView:LateUpdate () (at ./Noesis/Runtime/NoesisView.cs:1409)
 
User avatar
sfernandez
Site Admin
Posts: 3134
Joined: 22 Dec 2011, 19:20

Re: Can't get pixel scrolling to work with a ScrollViewer

02 Oct 2024, 12:01

A ScrollViewer delegates the scrolling to its IScrollInfo, which by default (CanContentScroll=False) is the ScrollContentPresenter defined in its template. A ScrollContentPresenter always does pixel scrolling, as it doesn't know anything about the content layout.

If you set CanContentScroll=True, then the content of the ScrollContentPresenter (usually a Panel) is set as the IScrollInfo in the ScrollViewer. A normal StackPanel used as IScrollInfo will only scroll by jumping items. If you have a VirtualizingStackPanel, then you can specify the VirtualizingPanel.ScrollUnit to "Pixel" or "Item" as you want.

Regarding the virtualization warning, it is indicating that the VirtualizingPanel has infinite available space to measure its children, so it won't virtualize anything. This happens for example if you don't set a fixed height in a ListBox and then put it inside a vertical StackPanel or a Canvas.

To better understand what is happening with the pixel scrolling I would need a minimal xaml showing the structure of this scenario (the ScrollViewer and its contents and templates used).
 
burst2flame
Topic Author
Posts: 26
Joined: 11 Mar 2024, 18:04

Re: Can't get pixel scrolling to work with a ScrollViewer

02 Oct 2024, 20:18

I tried a minimal example of what you said but it still doesn't work correctly. It's still doing it by item. I included my code and the default noesis theme code with the ScrollViewer.
Screenshot 2024-10-02 111527.png
MainView.xaml
<UserControl x:Class="Quantum_Survivor.MainView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
  xmlns:local="clr-namespace:Quantum_Survivor"
  d:DataContext="{d:DesignInstance {x:Type local:MainViewModel}, IsDesignTimeCreatable=True}">

    <ScrollViewer HorizontalAlignment="Stretch" Height="400" CanContentScroll="False" >
      <ScrollViewer.Background>
          <SolidColorBrush Color="Black" />
      </ScrollViewer.Background>
      <VirtualizingStackPanel ScrollUnit="Pixel" >
        <Rectangle Width="30" Height="1000" HorizontalAlignment="Left">
            <Rectangle.Fill>
                <RadialGradientBrush>
                    <GradientStop Color="Yellow" Offset="0" />
                    <GradientStop Color="Orange" Offset="0.5" />
                    <GradientStop Color="Red" Offset="1" />
                </RadialGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Width="30" Height="70" HorizontalAlignment="Right">
          <Rectangle.Fill>
              <RadialGradientBrush>
                  <GradientStop Color="Yellow" Offset="0" />
                  <GradientStop Color="Orange" Offset="0.5" />
                  <GradientStop Color="Red" Offset="1" />
              </RadialGradientBrush>
          </Rectangle.Fill>
      </Rectangle>
    </VirtualizingStackPanel>
  </ScrollViewer>
</UserControl>

Styles.xaml
    <!-- ScrollViewer -->
    <ControlTemplate x:Key="Template.ScrollViewer" TargetType="ScrollViewer">
        <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{DynamicResource Corner.Border0}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Decorator x:Name="ShowBarsRef" IsEnabled="False"/>
                <ScrollContentPresenter Grid.RowSpan="2" Grid.ColumnSpan="2" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" CanContentScroll="{TemplateBinding CanContentScroll}" Margin="{TemplateBinding Padding}"/>
                <Rectangle x:Name="Corner" Grid.Row="1" Grid.Column="1" Fill="{DynamicResource Brush.Track.Normal}" IsEnabled="False" Opacity="0"/>
                <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="0" Grid.Row="1" Orientation="Horizontal" MaxHeight="{TemplateBinding MinHeight}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Minimum="0" Maximum="{TemplateBinding ScrollableWidth}" Opacity="0"/>
                <ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="1" Grid.Row="0" Orientation="Vertical" MaxWidth="{TemplateBinding MinWidth}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" Minimum="0" Maximum="{TemplateBinding ScrollableHeight}" Opacity="0"/>
            </Grid>
        </Border>
        <ControlTemplate.Resources>
            <Storyboard x:Key="Anim.ShowBars" BeginTime="0:0:0.1">
                <DoubleAnimation Storyboard.TargetName="PART_HorizontalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.1" AccelerationRatio="0.5" DecelerationRatio="0.5"/>
                <DoubleAnimation Storyboard.TargetName="PART_VerticalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.1" AccelerationRatio="0.5" DecelerationRatio="0.5"/>
            </Storyboard>
            <Storyboard x:Key="Anim.HideBars" BeginTime="0:0:2">
                <DoubleAnimation Storyboard.TargetName="PART_HorizontalScrollBar" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.15" AccelerationRatio="0.75" DecelerationRatio="0.25"/>
                <DoubleAnimation Storyboard.TargetName="PART_VerticalScrollBar" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.15" AccelerationRatio="0.75" DecelerationRatio="0.25"/>
            </Storyboard>
            <Storyboard x:Key="Anim.ShowCorner" BeginTime="0:0:0.1">
                <DoubleAnimation Storyboard.TargetName="Corner" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.1" AccelerationRatio="0.75" DecelerationRatio="0.25"/>
            </Storyboard>
            <Storyboard x:Key="Anim.HideCorner" BeginTime="0:0:2">
                <DoubleAnimation Storyboard.TargetName="Corner" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.15" AccelerationRatio="0.75" DecelerationRatio="0.25"/>
            </Storyboard>
        </ControlTemplate.Resources>
        <ControlTemplate.Triggers>
            <Trigger Property="IsKeyboardFocusWithin" Value="True">
                <Setter Property="IsEnabled" Value="True" TargetName="ShowBarsRef"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="IsEnabled" Value="True" TargetName="ShowBarsRef"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="True" SourceName="ShowBarsRef">
                <Trigger.EnterActions>
                    <BeginStoryboard Storyboard="{StaticResource Anim.ShowBars}"/>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard Storyboard="{StaticResource Anim.HideBars}"/>
                </Trigger.ExitActions>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True" SourceName="PART_HorizontalScrollBar">
                <Setter Property="IsEnabled" Value="True" TargetName="Corner"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True" SourceName="PART_VerticalScrollBar">
                <Setter Property="IsEnabled" Value="True" TargetName="Corner"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="True" SourceName="Corner">
                <Trigger.EnterActions>
                    <BeginStoryboard Storyboard="{StaticResource Anim.ShowCorner}"/>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard Storyboard="{StaticResource Anim.HideCorner}"/>
                </Trigger.ExitActions>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    <Style TargetType="ScrollViewer" BasedOn="{StaticResource {x:Type ContentControl}}">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="PanningMode" Value="VerticalFirst"/>
        <Setter Property="Template" Value="{StaticResource Template.ScrollViewer}"/>
        <Setter Property="FocusVisualStyle" Value="{StaticResource Style.Focus.Outer.Uniform}"/>
    </Style>
 
burst2flame
Topic Author
Posts: 26
Joined: 11 Mar 2024, 18:04

Re: Can't get pixel scrolling to work with a ScrollViewer

03 Oct 2024, 18:26

Any word on this, it basically makes scrolling useless for me. It also seems like clipping works the same way.
 
User avatar
sfernandez
Site Admin
Posts: 3134
Joined: 22 Dec 2011, 19:20

Re: Can't get pixel scrolling to work with a ScrollViewer

03 Oct 2024, 20:56

I'm not able to reproduce your problem, just tried your UserControl xaml (without the x:Class and custom namespace) in XamlToy and it scrolls by pixel as expected, or maybe we're not talking about the same thing.

Apart from that you don't need a VirtualizingStackPanel in this case because you're not virtualizing anything, you can have a simply StackPanel:
<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ScrollViewer HorizontalAlignment="Stretch" Height="400" CanContentScroll="False" >
      <ScrollViewer.Background>
          <SolidColorBrush Color="Black" />
      </ScrollViewer.Background>
      <StackPanel>
        <Rectangle Width="30" Height="1000" HorizontalAlignment="Left">
            <Rectangle.Fill>
                <RadialGradientBrush>
                    <GradientStop Color="Yellow" Offset="0" />
                    <GradientStop Color="Orange" Offset="0.5" />
                    <GradientStop Color="Red" Offset="1" />
                </RadialGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Rectangle Width="30" Height="70" HorizontalAlignment="Right" Margin="0,0,30,0">
          <Rectangle.Fill>
              <RadialGradientBrush>
                  <GradientStop Color="Yellow" Offset="0" />
                  <GradientStop Color="Orange" Offset="0.5" />
                  <GradientStop Color="Red" Offset="1" />
              </RadialGradientBrush>
          </Rectangle.Fill>
      </Rectangle>
    </StackPanel>
  </ScrollViewer>
</UserControl>
Because the pixel scrolling is handled by the ScrollContentPresenter defined in the ScrollViewer template.
 
burst2flame
Topic Author
Posts: 26
Joined: 11 Mar 2024, 18:04

Re: Can't get pixel scrolling to work with a ScrollViewer

04 Oct 2024, 00:16

While you're example works in xaml toy, it doesn't work in unity. It's not clipping properly. Can you try and duplicate in unity and not xaml toy?
Screenshot 2024-10-03 151537.png
 
User avatar
jsantos
Site Admin
Posts: 4095
Joined: 20 Jan 2012, 17:18
Contact:

Re: Can't get pixel scrolling to work with a ScrollViewer

04 Oct 2024, 10:09

Hello, regarding the clipping issue, could you clarify whether this is a render to texture or a render directly to the camera? It seems that the stencil bits may be missing on the surface.

Could you also attach a RenderDoc capture of the frame so we can investigate further?
 
burst2flame
Topic Author
Posts: 26
Joined: 11 Mar 2024, 18:04

Re: Can't get pixel scrolling to work with a ScrollViewer

08 Oct 2024, 23:34

It's a render directly to the camera. It's seems like either I can't attach a render doc or it's too large. How can I send it to you?

Here are the view settings:
Screenshot 2024-10-08 100301.png
Here are the Noesis Settings:
Screenshot 2024-10-08 100236.png
 
User avatar
jsantos
Site Admin
Posts: 4095
Joined: 20 Jan 2012, 17:18
Contact:

Re: Can't get pixel scrolling to work with a ScrollViewer

09 Oct 2024, 14:59

Could you please create a ticket for this (make it private if necessary) and attach a link to the capture? If the file exceeds the attachment limits in the tracker, you'll need to upload it elsewhere and share the link
 
burst2flame
Topic Author
Posts: 26
Joined: 11 Mar 2024, 18:04

Re: Can't get pixel scrolling to work with a ScrollViewer

09 Oct 2024, 21:07

I think you can't upload the render doc type to the forums, but here is the render doc:



Where do I make a ticket? In the bugtracker?

Who is online

Users browsing this forum: Google [Bot] and 2 guests