From d944b8728cec0b32dcbeb4cc716f005bcc0bb43d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 9 Jul 2025 21:05:20 -0500 Subject: [PATCH] cmdpal: A sample for tracking load/unload for pages (#39265) Committing this sample for posterity's sake. This is the product of an experiment: "can an extension know when it's page was opened / closed?" And without changing the actual SDK, this **is** possible. It relies on the fact that CmdPal (the host) needs to register for the `ItemsChanged` event on list pages, and it does that when the page is loaded, and it unregisters itself when the page is closed. This does require manually implementing `IListPage` - you can't just `override` the `event` in the base class ([that's illegal](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1070)), and using `new` to shadow it doesn't work either (probably for cswinrt reasons). This is the best I came up with. --- .../ext/SamplePagesExtension/OnLoadPage.cs | 82 +++++++++++++++++++ .../SamplePagesExtension/SamplesListPage.cs | 5 ++ 2 files changed, 87 insertions(+) create mode 100644 src/modules/cmdpal/ext/SamplePagesExtension/OnLoadPage.cs diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/OnLoadPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/OnLoadPage.cs new file mode 100644 index 0000000000..fb2911e99d --- /dev/null +++ b/src/modules/cmdpal/ext/SamplePagesExtension/OnLoadPage.cs @@ -0,0 +1,82 @@ +// 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; +using System.Collections.Generic; +using System.Globalization; +using Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; +using Windows.Foundation; + +namespace SamplePagesExtension; + +internal sealed partial class OnLoadPage : IListPage +{ + private readonly List _items = new(); + + public IIconInfo Icon => new IconInfo("\uE8AB"); // switch + + public string Title => "Load/Unload sample"; + + public string PlaceholderText => "This page changes each time you load it"; + + public ICommandItem EmptyContent => new CommandItem() { Icon = new IconInfo("\uE8AB"), Title = "This page starts empty", Subtitle = "but go back and open it again" }; + + public IFilters Filters => null; + + public IGridProperties GridProperties => null; + + public bool HasMoreItems => false; + + public string SearchText => string.Empty; + + public bool ShowDetails => false; + + public OptionalColor AccentColor => default; + + public bool IsLoading => false; + + public string Id => string.Empty; + + public string Name => "Open"; + +#pragma warning disable CS0067 // The event is never used + public event TypedEventHandler PropChanged; + + private event TypedEventHandler InternalItemsChanged; +#pragma warning restore CS0067 // The event is never used + + public event TypedEventHandler ItemsChanged + { + add + { + InternalItemsChanged += value; + var nowString = DateTime.Now.ToString("T", CultureInfo.CurrentCulture); + var item = new ListItem(new NoOpCommand()) + { + Title = $"Loaded {nowString}", + Icon = new IconInfo("\uECCB"), // Radio button on + }; + _items.Add(item); + } + + remove + { + InternalItemsChanged -= value; + var nowString = DateTime.Now.ToString("T", CultureInfo.CurrentCulture); + var item = new ListItem(new NoOpCommand()) + { + Title = $"Unloaded {nowString}", + Icon = new IconInfo("\uECCA"), // Radio button off + }; + _items.Add(item); + } + } + + public IListItem[] GetItems() => _items.ToArray(); + + public void LoadMore() + { + } +} diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/SamplesListPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/SamplesListPage.cs index 3eeed6c2c2..23e15bbaa9 100644 --- a/src/modules/cmdpal/ext/SamplePagesExtension/SamplesListPage.cs +++ b/src/modules/cmdpal/ext/SamplePagesExtension/SamplesListPage.cs @@ -32,6 +32,11 @@ public partial class SamplesListPage : ListPage Title = "Dynamic List Page Command", Subtitle = "Changes the list of items in response to the typed query", }, + new ListItem(new OnLoadPage()) + { + Title = "Demo of OnLoad/OnUnload", + Subtitle = "Changes the list of items every time the page is opened / closed", + }, // Content pages new ListItem(new SampleContentPage())