[CmdPal] Add Sections and Separators for List Pages and Grid Pages (#43952)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This pull request adds sections and separators to ListPages and
GridPages

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #38267
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

Since `CollectionViewSource` was causing performance issues and
@zadjii-msft asked for a new approach, I came up with this idea, heavily
inspired by how separators work on the `ContextMenu`, `FiltersDropDown`
and `Details`.

The way this is currently working is: Any ListItem where `Section` is
not null and `Command` is null, is considered a Separator.

On my tests, this seems to be working fine. Tried to make this work
without changes to the API, but I think this needs to be discussed.

### Some of the possible enhancements to existing extensions

### Search apps

<img width="792" height="523" alt="Screenshot 2025-11-27 173618"
src="https://github.com/user-attachments/assets/f9f9a64d-3ec1-4f7e-922b-997a3a4d074d"
/>

### Window Walker

<img width="785" height="518" alt="Screenshot 2025-11-27 173728"
src="https://github.com/user-attachments/assets/230f647d-210a-4b60-9068-c8fff890d2c9"
/>

### Winget

<img width="809" height="497" alt="Screenshot 2025-11-27 174006"
src="https://github.com/user-attachments/assets/547529c1-7600-4438-8c3e-e872e0327650"
/>

### Search files

<img width="819" height="536" alt="image"
src="https://github.com/user-attachments/assets/e86accc0-3f85-412d-8fb0-914a5479baff"
/>

### Grid Pages

<img width="804" height="964" alt="Screenshot 2025-11-27 174055"
src="https://github.com/user-attachments/assets/a3bba7db-95df-47ec-9cfb-f38775ab960e"
/>



<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
This commit is contained in:
Guilherme
2025-12-10 23:51:42 -03:00
committed by GitHub
parent a08fc0921f
commit 94ace730c8
15 changed files with 1146 additions and 60 deletions

View File

@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections;
namespace Microsoft.CommandPalette.Extensions.Toolkit;
public sealed partial class Section : IEnumerable<IListItem>
{
public IListItem[] Items { get; set; } = [];
public string SectionTitle { get; set; } = string.Empty;
private Separator CreateSectionListItem()
{
return new Separator(SectionTitle);
}
public Section(string sectionName, IListItem[] items)
{
SectionTitle = sectionName;
var listItems = items.ToList();
if (listItems.Count > 0)
{
listItems.Insert(0, CreateSectionListItem());
Items = [.. listItems];
}
}
public Section()
{
}
public IEnumerator<IListItem> GetEnumerator() => Items.ToList().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

View File

@@ -4,6 +4,40 @@
namespace Microsoft.CommandPalette.Extensions.Toolkit;
public partial class Separator : ISeparatorContextItem, ISeparatorFilterItem
public partial class Separator : IListItem, ISeparatorContextItem, ISeparatorFilterItem
{
public Separator(string? title = "")
: base()
{
Section = title ?? string.Empty;
Command = null;
}
public IDetails? Details => null;
public string? Section { get; private set; }
public ITag[]? Tags => null;
public string? TextToSuggest => null;
public ICommand? Command { get; private set; }
public IIconInfo? Icon => null;
public IContextItem[]? MoreCommands => null;
public string? Subtitle => null;
public string? Title
{
get => Section;
set => Section = value;
}
public event Windows.Foundation.TypedEventHandler<object, IPropChangedEventArgs>? PropChanged
{
add { }
remove { }
}
}