Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions samples/SampleApp/DemoPages/GroupedTileListBoxDemo.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@
<TextBlock TextWrapping="Wrap" Foreground="{DynamicResource TextControlPlaceholderForeground}">
SelectionMode="Multiple" with SelectedItems bound two-way.
Pointer: click replaces, Ctrl/Cmd+click toggles, Shift+click selects a range.
Drag on empty space to marquee-select (Ctrl/Cmd+drag adds to the selection); drag past the top/bottom edge to auto-scroll.
Comment thread
xfortin-devolutions marked this conversation as resolved.
Keyboard: arrows move, Shift+arrows extend the range, Ctrl/Cmd+Space toggles the current tile, Ctrl/Cmd+A selects all.
</TextBlock>

Expand Down Expand Up @@ -344,11 +345,10 @@
<!-- Resizable Grid -->
<Grid Height="400" ColumnDefinitions="2*,Auto,*">
<GroupedTileListBox Grid.Column="0"
ItemsSource="{Binding GroupedItems}"
ItemsSource="{Binding MultiSelectGroupedItems}"
Comment thread
rbstp marked this conversation as resolved.
SelectionMode="Multiple"
SelectedItems="{Binding MultiSelectedItems}"
GroupSelector="{Binding CategoryGroupSelector}"
GroupOrderSelector="{Binding CategoryGroupOrderSelector}"
GroupOrderAlphabetical="True"
ItemWidth="120"
ItemHeight="100"
Expand Down
32 changes: 32 additions & 0 deletions samples/SampleApp/ViewModels/GroupedTileListBoxViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,38 @@ private void SelectLargeAtTarget()
// the control mutates this collection directly and the demo observes it live.
public AvaloniaList<FoodItem> MultiSelectedItems { get; } = new();

// Scenario 5 source. Deliberately large and multi-grouped (many groups, many items per group,
// uneven counts so last rows are partial) so marquee drag-selection, cross-group rectangles, and
// edge auto-scroll can all be exercised. Kept separate from GroupedItems so Scenario 1 is unaffected.
public List<FoodItem> MultiSelectGroupedItems { get; } = GenerateMultiSelectItems();

private static List<FoodItem> GenerateMultiSelectItems()
{
// (group label, item count) — varied counts on purpose to produce partial last rows.
(string Group, int Count)[] groups =
{
("Group A", 42),
("Group B", 55),
("Group C", 63),
("Group D", 48),
("Group E", 70),
("Group F", 39),
("Group G", 58),
("Group H", 51),
};

var items = new List<FoodItem>();
foreach ((string group, int count) in groups)
{
for (int i = 1; i <= count; i++)
{
items.Add(new FoodItem($"{group} · {i:D2}", group));
}
}

return items;
}

// Scenario 1: Named groups
public List<FoodItem> GroupedItems { get; } = new()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<!-- Marquee (drag-to-select rectangle) brushes. Accent-tinted to match the Explorer-style
rubber-band; theme-aware via SystemAccentColor, so no per-theme override is required. -->
<SolidColorBrush x:Key="GroupedTileListBoxSelectionRectangleFill"
Color="{DynamicResource SystemAccentColor}" Opacity="0.2" />
<SolidColorBrush x:Key="GroupedTileListBoxSelectionRectangleBorderBrush"
Color="{DynamicResource SystemAccentColor}" Opacity="0.8" />

<ControlTheme x:Key="{x:Type GroupedTileListBox}" TargetType="GroupedTileListBox">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="4" />
Expand Down Expand Up @@ -29,10 +36,25 @@
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
ClipToBounds="True">
<ScrollViewer Name="PART_ScrollViewer"
Background="{TemplateBinding Background}"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto" />
<Panel>
<ScrollViewer Name="PART_ScrollViewer"
Background="{TemplateBinding Background}"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto" />
<!--
Marquee overlay. Shares the ScrollViewer's origin so a pointer
position relative to PART_ScrollViewer maps directly onto this Canvas
(viewport space) and onto content space (viewport + Offset). It never
scrolls with content and never intercepts pointer input.
-->
<Canvas Name="PART_SelectionLayer" IsHitTestVisible="False">
<Border Name="PART_SelectionRectangle"
IsVisible="False"
BorderThickness="1"
Background="{DynamicResource GroupedTileListBoxSelectionRectangleFill}"
BorderBrush="{DynamicResource GroupedTileListBoxSelectionRectangleBorderBrush}" />
</Canvas>
</Panel>
</Border>
</Panel>
</ControlTemplate>
Expand Down
Loading