diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleUpdateListPage.cs b/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleUpdateListPage.cs new file mode 100644 index 000000000000..bd972ea21b23 --- /dev/null +++ b/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleUpdateListPage.cs @@ -0,0 +1,66 @@ +// 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.Threading.Tasks; +using Microsoft.CmdPal.Extensions; +using Microsoft.CmdPal.Extensions.Helpers; + +namespace SamplePagesExtension; + +internal sealed partial class SampleUpdateListPage : DynamicListPage +{ + private bool _items; + + public SampleUpdateListPage() + { + Icon = new(string.Empty); + Name = "SSH Keychain"; + + // Start the background task to update the Items boolean every 5 seconds + StartPeriodicUpdate(); + } + + // This method starts a Task that runs in the background and updates Items every 5 seconds + private void StartPeriodicUpdate() + { + Task.Run(async () => + { + while (true) + { + await Task.Delay(5000); // Wait for 5 seconds + + // Toggle the Items boolean + _items = !_items; + this.Items = _items; + } + }); + } + + public override ISection[] GetItems(string query) + { + // Change the list items based on the value of _items + var listItems = _items + ? new List + { + new(new NoOpCommand()) { Title = "Items is TRUE - Item 1", Subtitle = "This is dynamically generated content" }, + new(new NoOpCommand()) { Title = "Items is TRUE - Item 2", Subtitle = "This list updates every 5 seconds" }, + } + : new List + { + new(new NoOpCommand()) { Title = "Items is FALSE - Item 1", Subtitle = "Items is currently false" }, + new(new NoOpCommand()) { Title = "Items is FALSE - Item 2", Subtitle = "The content will change again in 5 seconds" }, + }; + + return new ISection[] + { + new ListSection() + { + Title = "Updating List Section", + Items = listItems.ToArray(), + }, + }; + } +} diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Properties/launchSettings.json b/src/modules/cmdpal/Exts/SamplePagesExtension/Properties/launchSettings.json index 36ae99389449..fd69489f647a 100644 --- a/src/modules/cmdpal/Exts/SamplePagesExtension/Properties/launchSettings.json +++ b/src/modules/cmdpal/Exts/SamplePagesExtension/Properties/launchSettings.json @@ -1,7 +1,8 @@ { "profiles": { "SamplePagesExtension (Package)": { - "commandName": "MsixPackage" + "commandName": "MsixPackage", + "commandLineArgs": "-RegisterProcessAsComServer" }, "SamplePagesExtension (Unpackaged)": { "commandName": "Project" diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesCommandsProvider.cs b/src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesCommandsProvider.cs index 5e4b6736317a..e5fc7b05831a 100644 --- a/src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesCommandsProvider.cs +++ b/src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesCommandsProvider.cs @@ -39,6 +39,10 @@ public partial class SamplePagesCommandsProvider : ICommandProvider { Title = "Dynamic List Page Command", Subtitle = "SamplePages Extension", + }, + new ListItem(new SampleUpdateListPage()) + { + Title = "Updating List Page Command", } ]; diff --git a/src/modules/cmdpal/WindowsCommandPalette/PageViewModel.cs b/src/modules/cmdpal/WindowsCommandPalette/PageViewModel.cs index 5c6350f324f4..4fd0b1ba0520 100644 --- a/src/modules/cmdpal/WindowsCommandPalette/PageViewModel.cs +++ b/src/modules/cmdpal/WindowsCommandPalette/PageViewModel.cs @@ -2,17 +2,35 @@ // 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.ComponentModel; using Microsoft.CmdPal.Extensions; +using Microsoft.UI.Dispatching; using Windows.Foundation; namespace DeveloperCommandPalette; -public class PageViewModel +public class PageViewModel : INotifyPropertyChanged { + private readonly DispatcherQueue dispatcherQueue; + + public event PropertyChangedEventHandler? PropertyChanged; + public bool Nested { get; set; } public IPage PageAction { get; } + private bool items; + + public bool Items + { + get => items; + set + { + items = value; + BubbleXamlPropertyChanged(nameof(items)); + } + } + // public IPage PageAction { get => pageAction; set => pageAction = value; } public ActionViewModel Command { get; } @@ -24,8 +42,30 @@ public class PageViewModel protected PageViewModel(IPage page) { + page.PropChanged += Page_PropertyChanged; PageAction = page; Command = new(page); + + this.dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + } + + private void Page_PropertyChanged(object sender, PropChangedEventArgs args) + { + BubbleXamlPropertyChanged(args.PropertyName); + } + + private void BubbleXamlPropertyChanged(string propertyName) + { + if (this.dispatcherQueue == null) + { + // this is highly unusual + return; + } + + this.dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () => + { + this.PropertyChanged?.Invoke(this, new(propertyName)); + }); } public void DoAction(ActionViewModel action) diff --git a/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml b/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml index acf77b3076ad..cea7acda03f4 100644 --- a/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml +++ b/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml @@ -17,7 +17,7 @@ - + diff --git a/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml.cs b/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml.cs index 838439428d4a..53e81a1f2828 100644 --- a/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml.cs +++ b/src/modules/cmdpal/WindowsCommandPalette/Views/ListPage.xaml.cs @@ -77,6 +77,8 @@ protected override void OnNavigatedTo(NavigationEventArgs e) return; } + ViewModel.PropertyChanged += ViewModel_PropertyChanged; + if (e.NavigationMode == NavigationMode.New) { ViewModel.InitialRender().ContinueWith((t) => @@ -212,6 +214,35 @@ private void Page_Loaded(object sender, RoutedEventArgs e) } } + private void ViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) + { + // Check if the property changed is 'Items' + if (e.PropertyName == nameof(ViewModel.Items)) + { + if (ViewModel != null) + { + // Call UpdateFilter when 'Items' changes + DispatcherQueue.TryEnqueue(async () => + { + await ViewModel.UpdateListItems(); + if (ItemsList.Items.Count > 0) + { + ItemsList.SelectedIndex = 0; + } + }); + } + } + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + base.OnNavigatedFrom(e); + if (ViewModel != null) + { + ViewModel.PropertyChanged -= ViewModel_PropertyChanged; + } + } + private void FilterBox_KeyDown(object sender, KeyRoutedEventArgs e) { if (e.Handled) diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CmdPal.Extensions.Helpers/ListPage.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CmdPal.Extensions.Helpers/ListPage.cs index 63bb85fee5f8..97470e751e6d 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CmdPal.Extensions.Helpers/ListPage.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CmdPal.Extensions.Helpers/ListPage.cs @@ -5,6 +5,7 @@ public class ListPage : Page, IListPage private string _placeholderText = string.Empty; private string _searchText = string.Empty; private bool _showDetails; + private bool _items; private IFilters? _filters; private IGridProperties? _gridProperties; @@ -28,6 +29,16 @@ public string SearchText } } + public bool Items + { + get => _items; + set + { + _items = value; + OnPropertyChanged(nameof(Items)); + } + } + public bool ShowDetails { get => _showDetails;