上一篇: 添加命令。
到目前为止,我们已演示如何返回扩展中的静态项列表。 但是,你的项目也可以更改,以显示实时数据或者反映系统的状态。 本文介绍如何更新扩展中的命令列表。
更新命令
命令面板中几乎所有扩展对象都实现了 IPropChanged 接口。 这使得他们能够在发生变化时通知命令面板,然后命令面板将更新 UI 以反映这些变化。 如果使用工具包实现,则已针对支持该接口的属性实现此接口。
作为一个简单的示例,可以更新页面的标题。 为此,可以添加一个命令,该命令将仅更新页面的标题。
public override IListItem[] GetItems()
{
OpenUrlCommand command = new("https://learn.microsoft.com/windows/powertoys/command-palette/creating-an-extension");
AnonymousCommand updateCommand = new(action: () => { Title += " Hello"; }) { Result = CommandResult.KeepOpen() };
return [
new ListItem(command)
{
Title = "Open the Command Palette documentation",
},
new ListItem(updateCommand),
];
}
在这里,我们使用 AnonymousCommand 创建将更新页面标题的命令。 AnonymousCommand 是一个帮助程序,可用于创建不需要重复使用的简单轻型命令。
当然也可以创建自定义 ListItem 对象:
internal sealed partial class IncrementingListItem : ListItem
{
public IncrementingListItem() :
base(new NoOpCommand())
{
Command = new AnonymousCommand(action: Increment) { Result = CommandResult.KeepOpen() };
Title = "Increment";
}
private void Increment()
{
Subtitle = $"Count = {++_count}";
}
private int _count;
}
public override IListItem[] GetItems()
{
OpenUrlCommand command = new("https://learn.microsoft.com/windows/powertoys/command-palette/creating-an-extension");
return [
new ListItem(command)
{
Title = "Open the Command Palette documentation",
},
new ListItem(new ShowMessageCommand()),
+ new IncrementingListItem(),
];
}
你正在以命令面板扩展的形式创建自己的空闲点击器游戏。
更新命令列表
还可以更改页面上的项目列表。 这对于异步加载结果的页面或基于应用状态显示不同命令的页面非常有用。
为此,可以在 ListPage 对象上使用 RaiseItemsChanged 方法。 这会通知命令面板项列表已更改,并应重新提取项列表。 例如,让我们利用上面的 IncrementingListItem 来更新页面上的项目列表。
更新列表项以引用页面,并添加一种方法来递增计数:
internal sealed partial class IncrementingListItem : ListItem
{
public IncrementingListItem(<ExtensionName>Page page) :
base(new NoOpCommand())
{
_page = page;
Command = new AnonymousCommand(action: _page.Increment) { Result = CommandResult.KeepOpen() };
Title = "Increment";
}
private <ExtensionName>Page _page;
}
然后,按如下所示更改页面:
public <ExtensionName>Page()
{
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.png");
Title = "My sample extension";
Name = "Open";
_items = [new IncrementingListItem(this) { Subtitle = $"Item 0" }];
}
public override IListItem[] GetItems()
{
return _items.ToArray();
}
internal void Increment()
{
_items.Add(new IncrementingListItem(this) { Subtitle = $"Item {_items.Count}" });
RaiseItemsChanged();
}
private List<ListItem> _items;
现在,每次执行 IncrementingListItem 命令之一时,页面上的项列表都将更新以添加另一项。 我们使用页面专有的单个 列表 来管理所有项目。 值得注意的是,在调用 RaiseItemsChanged 之前,我们将在 Increment 方法中创建新项。 IInvokableCommand 调用的执行时长可以根据需要灵活调整。 所有代码都在与命令面板相独立的一个进程中运行,因此不会阻碍用户界面。 但在调用 RaiseItemsChanged 之前构造项目将有助于使你的扩展在响应方面表现更好。
显示加载旋转图标
到目前为止,一切都相当迅速地进行。 许多扩展程序可能需要完成一些需要花费更长时间的任务。 在这种情况下,可以将 Page.IsLoading 设置为 true
显示加载微调器。 这将有助于指示扩展正在后台执行一些操作。
注释
如果从上一部分进行操作,请将下面的代码从 Page.IsLoading
修改为 this.IsLoading
。
internal void Increment()
{
Page.IsLoading = true;
Task.Run(() =>
{
Thread.Sleep(5000);
_items.Add(new IncrementingListItem(this) { Subtitle = $"Item {_items.Count}" });
RaiseItemsChanged();
Page.IsLoading = false;
});
}
最佳做法是在开始工作之前将 IsLoading 设置为 true
。 然后执行所有工作以生成需要向用户显示的所有新 ListItems 。 然后,在项目准备就绪后,调用 RaiseItemsChanged 并将 IsLoading 设置回 false
。 这将确保在整个任务持续期间显示加载动画,并在任务完成后立即更新用户界面(无需等待扩展构造新的 ListItem 对象)。