AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
26.11k stars 2.26k forks source link

VirtualizingStackPanel Spacing property #17336

Open Neakita opened 1 month ago

Neakita commented 1 month ago

Is your feature request related to a problem? Please describe.

When using ListBox with ItemPanel = StackPanel it's possible to use StackPanel's Spacing property for, well, adding spacing between items:

<ControlTheme x:Key="{x:Type ListBox}" TargetType="ListBox">
        ...
        <Setter Property="ItemsPanel">
            <ItemsPanelTemplate>
                <StackPanel Spacing="12"/>
            </ItemsPanelTemplate>
        </Setter>
                ...

which is simple and straightforward.

But when i need virtualization i have to use VirtualizingStackPanel for ListBox's ItemPanel which doesn't have the Spacing property.

Describe the solution you'd like

Register or AddOwner of StackPanel.SpacingProperty in VirtualizingStackPanel so it's possible to set Spacing between items in VirtualizingStackPanel in the same way as it is with StackPanel:

<ControlTheme x:Key="{x:Type ListBox}" TargetType="ListBox">
        ...
        <Setter Property="ItemsPanel">
            <ItemsPanelTemplate>
                <VirtualizingStackPanel Spacing="12"/>
            </ItemsPanelTemplate>
        </Setter>
                ...

which will require changes in Measure/Arrange code.

Describe alternatives you've considered

Simulate Spacing with ListBoxItem margin and compensation of it's margin at the start and end of the ListBox with same but negative margin:

    <ControlTheme x:Key="BaseListBoxItem" TargetType="ListBoxItem">
        ...
                <!--Could StackPanel.Spacing be used unless VirtualizingStackPanel is required which doesn't have the Spacing property-->
                <Setter Property="Margin" Value="0 6"/>
        ...
    </ControlTheme>
<ControlTheme x:Key="{x:Type ListBox}" TargetType="ListBox">
        ...
        <Setter Property="Template">
            ...
                        <!--Compensation of ListBoxItem internal margin used to simulate StackPanel.Spacing even if VirtualizingStackPanel is used-->
                        <Decorator Margin="0 -6">
                            ...
                        </Decorator>
                    ...
        </Setter>
        ...
</ControlTheme>

which is an ugly crutch and will require additional markup for both Horizontal-Vertical layouts support.

Additional context

No response

wieslawsoltes commented 1 month ago

You can implement spacing using nth-child selector

Neakita commented 1 month ago

You can implement spacing using nth-child selector

Are you suggesting to set default item's margin to something like 0 6 0 0 and set the first item's margin to zero with :nth-child(1) selector?

maxkatz6 commented 1 month ago

Another option, which I often use, is adding Marging to all elements, and adding negative margin on the common container. But yes, VirtualizingStackPanel.Spacing would be a really nice improvement.

Neakita commented 1 month ago

Another option, which I often use, is adding Marging to all elements, and adding negative margin on the common container.

Exactly what i did for now, see Describe alternatives you've considered section.

timunie commented 1 month ago

@Neakita maybe you want to file a PR?

Neakita commented 1 month ago

@Neakita maybe you want to file a PR?

I do not exclude this possibility. I'll probably try to do this over the next few days if I don't have any difficulties cloning the repository, testing changes, or anything else.