Let a group be right-clicked, as a host already can

The host cards have had a menu since the grid replaced the sidebar; the group
cards above them had a double-click and two buttons beside the heading, and
nothing that named the card under the pointer. Open, Edit and Delete are on them
now, drawn and aimed the same way.

On the list rather than in the item template, for the reason the host grid's is:
the three commands are the vault's, and a ContextMenu inside a DataTemplate has
the row for its data context, so every binding in it would silently resolve to
nothing. The code-behind selects whatever was right-clicked before the menu
opens, and that is what makes one menu act on the card under the pointer rather
than on whichever was selected before.

**Cancelled over the space around the cards, and here that guard is doing more
than the host grid's.** GroupTarget falls back to the group whose contents are on
screen when no card is selected — the right answer for a pair of buttons beside
the heading, which would otherwise have no subject the moment a group with
nothing inside it is opened, and the wrong one for a menu that opened on a card.
Without the guard, right-clicking the gap beside the cards would offer to delete
the group the trail ends with: a question about something the user is not
pointing at, in the one menu where the answer is a deletion.

Only Open takes a parameter, and it has to. OpenGroupCommand's null is a real
argument rather than a missing one — it is the trail's first crumb, ALL HOSTS —
so an entry with no parameter would not open the card, it would leave the group
the user right-clicked and go back to the top level.

Two tests beside the two the host menu already had. What they hold that a build
cannot is the CommandParameter binding: a path that resolves to nothing compiles
and draws, and the entry would then quietly do the opposite of what it says. The
popup itself is still the platform's, so manual-checks 7.9 gained the group half
of the same check.
This commit is contained in:
2026-08-04 16:27:01 +02:00
parent 7f5b871c47
commit be012585b3
4 changed files with 160 additions and 5 deletions
@@ -282,6 +282,34 @@
<ListBox.ItemsPanel>
<ItemsPanelTemplate><WrapPanel /></ItemsPanelTemplate>
</ListBox.ItemsPanel>
<!--
The three things you can do to a group, on the group itself — the same menu the host grid
below has, for the same reasons. On the list rather than in the item template, because the
commands are the vault's and a menu inside a DataTemplate would have the row for its data
context; the code-behind selects whatever was right-clicked before the menu opens, and
cancels it outright over the space around the cards.
Open is here as well as on the double-click, and Edit and Delete as well as on the two
buttons above, and neither is a duplicate for its own sake: a gesture is unreachable without
a pointer, and the buttons act on GroupTarget — which with no card selected is the group the
trail ends with rather than the one under the pointer. This menu is the one place all three
act on the card that was right-clicked.
Only Open takes a parameter, because OpenGroupCommand's null means ALL HOSTS rather than
nothing; Edit and Delete read GroupTarget, which the selection the code-behind has just made
is the first half of.
-->
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Open" Command="{Binding OpenGroupCommand}"
CommandParameter="{Binding SelectedGroup}" />
<MenuItem Header="Edit…" Command="{Binding EditGroupCommand}" />
<Separator />
<MenuItem Header="Delete…" Command="{Binding DeleteGroupCommand}" />
</ContextMenu>
</ListBox.ContextMenu>
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:HostGroupRowViewModel">
<Border Classes="tile">