mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
CmdPal: Filters for DynamicListPage? Yes, please. (#40783)
Closes: #40382 ## To-do list - [x] Add support for "single-select" filters to DynamicListPage - [x] Filters can contain icons - [x] Filter list can contain separators - [x] Update Windows Services built-in extension to support filtering by all, started, stopped, and pending services - [x] Update SampleExtension dynamic list sample to filter. ## Example of filters in use ```C# internal sealed partial class ServicesListPage : DynamicListPage { public ServicesListPage() { Icon = Icons.ServicesIcon; Name = "Windows Services"; var filters = new ServiceFilters(); filters.PropChanged += Filters_PropChanged; Filters = filters; } private void Filters_PropChanged(object sender, IPropChangedEventArgs args) => RaiseItemsChanged(); public override void UpdateSearchText(string oldSearch, string newSearch) => RaiseItemsChanged(); public override IListItem[] GetItems() { // ServiceHelper.Search knows how to filter based on the CurrentFilterIds provided var items = ServiceHelper.Search(SearchText, Filters.CurrentFilterIds).ToArray(); return items; } } public partial class ServiceFilters : Filters { public ServiceFilters() { // This would be a default selection. Not providing this will cause the filter // control to display the "Filter" placeholder text. CurrentFilterIds = ["all"]; } public override IFilterItem[] GetFilters() { return [ new Filter() { Id = "all", Name = "All Services" }, new Separator(), new Filter() { Id = "running", Name = "Running", Icon = Icons.GreenCircleIcon }, new Filter() { Id = "stopped", Name = "Stopped", Icon = Icons.RedCircleIcon }, new Filter() { Id = "paused", Name = "Paused", Icon = Icons.PauseIcon }, ]; } } ``` ## Current example of behavior https://github.com/user-attachments/assets/2e325763-ad3a-4445-bbe2-a840df08d0b3 --------- Co-authored-by: Mike Griese <migrie@microsoft.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
// 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;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
@@ -16,9 +17,14 @@ internal sealed partial class SampleDynamicListPage : DynamicListPage
|
||||
Icon = new IconInfo(string.Empty);
|
||||
Name = "Dynamic List";
|
||||
IsLoading = true;
|
||||
var filters = new SampleFilters();
|
||||
filters.PropChanged += Filters_PropChanged;
|
||||
Filters = filters;
|
||||
}
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch) => RaiseItemsChanged(newSearch.Length);
|
||||
private void Filters_PropChanged(object sender, IPropChangedEventArgs args) => RaiseItemsChanged();
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch) => RaiseItemsChanged();
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
@@ -28,6 +34,23 @@ internal sealed partial class SampleDynamicListPage : DynamicListPage
|
||||
items = [new ListItem(new NoOpCommand()) { Title = "Start typing in the search box" }];
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Filters.CurrentFilterId))
|
||||
{
|
||||
switch (Filters.CurrentFilterId)
|
||||
{
|
||||
case "mod2":
|
||||
items = items.Where((item, index) => (index + 1) % 2 == 0).ToArray();
|
||||
break;
|
||||
case "mod3":
|
||||
items = items.Where((item, index) => (index + 1) % 3 == 0).ToArray();
|
||||
break;
|
||||
case "all":
|
||||
default:
|
||||
// No filtering
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (items.Length > 0)
|
||||
{
|
||||
items[0].Subtitle = "Notice how the number of items changes for this page when you type in the filter box";
|
||||
@@ -36,3 +59,18 @@ internal sealed partial class SampleDynamicListPage : DynamicListPage
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable SA1402 // File may only contain a single type
|
||||
public partial class SampleFilters : Filters
|
||||
#pragma warning restore SA1402 // File may only contain a single type
|
||||
{
|
||||
public override IFilterItem[] GetFilters()
|
||||
{
|
||||
return
|
||||
[
|
||||
new Filter() { Id = "all", Name = "All" },
|
||||
new Filter() { Id = "mod2", Name = "Every 2nd", Icon = new IconInfo("2") },
|
||||
new Filter() { Id = "mod3", Name = "Every 3rd", Icon = new IconInfo("3") },
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ internal sealed partial class SampleListPage : ListPage
|
||||
Title = "I'm a second command",
|
||||
RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1),
|
||||
},
|
||||
new SeparatorContextItem(),
|
||||
new Separator(),
|
||||
new CommandContextItem(
|
||||
new ToastCommand("Third command invoked", MessageState.Error) { Name = "Do 3", Icon = new IconInfo("\uF148") }) // dial 3
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user