mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
## Summary of the Pull Request This PR fixes three issues in one go: - Restores missing icons in app context menus. - Fixes propagation of changes from a command item to the context menu item for the primary action. - Ensures the context menus stay in sync when underlying command items change. Details: - Correctly propagates updates of name, icon, and subtitle from a command item to its primary command (`CommandItemViewModel._defaultCommandContextItemViewModel`). - Correctly propagate updates of command's name to title (`CommandItem.ctor`). - Fixes icon loading for application items: `AppCommand` no longer loads an app icon by default but instead relies on the caller to provide one (since `AppListItem` also handles icon loading). - Adds a generic fallback icon for apps when an icon cannot be loaded. - Updates bindings on context menu items to `OneWay`, ensuring the UI properly reflects item changes. - Adds a sample that showcases dynamically updated commands (with cats and dolphins!) to _Samples → List Page Sample Command_. ⚠️ Toolkit changes: - `CommandItem` won't capture assigned Command's name as its `Title`. This will allow it to propagate future changes to `Command.Name`. Pictures? Moving ones! https://github.com/user-attachments/assets/1a482394-d222-4f7c-9922-bb67d47dc566 <img width="864" height="538" alt="image" src="https://github.com/user-attachments/assets/12f07b3e-f41c-4c40-a4e5-315f40676c52" /> <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #40946 - [x] Related: #40991 - [ ] **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 <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
136 lines
3.1 KiB
C#
136 lines
3.1 KiB
C#
// 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.
|
|
|
|
namespace Microsoft.CommandPalette.Extensions.Toolkit;
|
|
|
|
public partial class CommandItem : BaseObservable, ICommandItem
|
|
{
|
|
private ICommand? _command;
|
|
private WeakEventListener<CommandItem, object, IPropChangedEventArgs>? _commandListener;
|
|
private string _title = string.Empty;
|
|
|
|
public virtual IIconInfo? Icon
|
|
{
|
|
get => field;
|
|
set
|
|
{
|
|
field = value;
|
|
OnPropertyChanged(nameof(Icon));
|
|
}
|
|
}
|
|
|
|
public virtual string Title
|
|
{
|
|
get => !string.IsNullOrEmpty(_title) ? _title : _command?.Name ?? string.Empty;
|
|
|
|
set
|
|
{
|
|
_title = value;
|
|
OnPropertyChanged(nameof(Title));
|
|
}
|
|
}
|
|
|
|
public virtual string Subtitle
|
|
{
|
|
get;
|
|
set
|
|
{
|
|
field = value;
|
|
OnPropertyChanged(nameof(Subtitle));
|
|
}
|
|
}
|
|
|
|
= string.Empty;
|
|
|
|
public virtual ICommand? Command
|
|
{
|
|
get => _command;
|
|
set
|
|
{
|
|
if (_commandListener is not null)
|
|
{
|
|
_commandListener.Detach();
|
|
_commandListener = null;
|
|
}
|
|
|
|
_command = value;
|
|
|
|
if (value is not null)
|
|
{
|
|
_commandListener = new(this, OnCommandPropertyChanged, listener => value.PropChanged -= listener.OnEvent);
|
|
value.PropChanged += _commandListener.OnEvent;
|
|
}
|
|
|
|
OnPropertyChanged(nameof(Command));
|
|
if (string.IsNullOrEmpty(_title))
|
|
{
|
|
OnPropertyChanged(nameof(Title));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnCommandPropertyChanged(CommandItem instance, object source, IPropChangedEventArgs args)
|
|
{
|
|
// command's name affects Title only if Title wasn't explicitly set
|
|
if (args.PropertyName == nameof(ICommand.Name) && string.IsNullOrEmpty(_title))
|
|
{
|
|
instance.OnPropertyChanged(nameof(Title));
|
|
}
|
|
}
|
|
|
|
public virtual IContextItem[] MoreCommands
|
|
{
|
|
get;
|
|
set
|
|
{
|
|
field = value;
|
|
OnPropertyChanged(nameof(MoreCommands));
|
|
}
|
|
}
|
|
|
|
= [];
|
|
|
|
public CommandItem()
|
|
: this(new NoOpCommand())
|
|
{
|
|
}
|
|
|
|
public CommandItem(ICommand command)
|
|
{
|
|
Command = command;
|
|
}
|
|
|
|
public CommandItem(ICommandItem other)
|
|
{
|
|
Command = other.Command;
|
|
Subtitle = other.Subtitle;
|
|
Icon = (IconInfo?)other.Icon;
|
|
MoreCommands = other.MoreCommands;
|
|
}
|
|
|
|
public CommandItem(
|
|
string title,
|
|
string subtitle = "",
|
|
string name = "",
|
|
Action? action = null,
|
|
ICommandResult? result = null)
|
|
{
|
|
var c = new AnonymousCommand(action);
|
|
if (!string.IsNullOrEmpty(name))
|
|
{
|
|
c.Name = name;
|
|
}
|
|
|
|
if (result is not null)
|
|
{
|
|
c.Result = result;
|
|
}
|
|
|
|
Command = c;
|
|
|
|
Title = title;
|
|
Subtitle = subtitle;
|
|
}
|
|
}
|