2025-05-28 14:35:26 -05:00
|
|
|
|
// 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.
|
|
|
|
|
|
|
2025-08-12 07:44:23 +08:00
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2025-07-15 12:21:44 -05:00
|
|
|
|
using Microsoft.CmdPal.Core.ViewModels;
|
2025-05-28 14:35:26 -05:00
|
|
|
|
using Microsoft.UI.Xaml;
|
|
|
|
|
|
using Microsoft.UI.Xaml.Controls;
|
2025-07-09 14:53:47 -05:00
|
|
|
|
using Microsoft.UI.Xaml.Controls.Primitives;
|
|
|
|
|
|
using Microsoft.UI.Xaml.Data;
|
2025-05-28 14:35:26 -05:00
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.CmdPal.UI;
|
|
|
|
|
|
|
2025-08-12 07:44:23 +08:00
|
|
|
|
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
|
2025-05-28 14:35:26 -05:00
|
|
|
|
internal sealed partial class ContextItemTemplateSelector : DataTemplateSelector
|
|
|
|
|
|
{
|
|
|
|
|
|
public DataTemplate? Default { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
public DataTemplate? Critical { get; set; }
|
|
|
|
|
|
|
2025-07-09 14:53:47 -05:00
|
|
|
|
public DataTemplate? Separator { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
protected override DataTemplate? SelectTemplateCore(object item, DependencyObject dependencyObject)
|
2025-05-28 14:35:26 -05:00
|
|
|
|
{
|
2025-07-09 14:53:47 -05:00
|
|
|
|
DataTemplate? dataTemplate = Default;
|
|
|
|
|
|
|
|
|
|
|
|
if (dependencyObject is ListViewItem li)
|
|
|
|
|
|
{
|
|
|
|
|
|
li.IsEnabled = true;
|
|
|
|
|
|
|
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>
2025-08-21 05:40:09 -05:00
|
|
|
|
if (item is SeparatorViewModel)
|
2025-07-09 14:53:47 -05:00
|
|
|
|
{
|
|
|
|
|
|
li.IsEnabled = false;
|
|
|
|
|
|
li.AllowFocusWhenDisabled = false;
|
|
|
|
|
|
li.AllowFocusOnInteraction = false;
|
|
|
|
|
|
dataTemplate = Separator;
|
|
|
|
|
|
}
|
2025-07-28 08:32:08 -05:00
|
|
|
|
else if (item is CommandContextItemViewModel commandItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
dataTemplate = commandItem.IsCritical ? Critical : Default;
|
|
|
|
|
|
}
|
2025-07-09 14:53:47 -05:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-07-28 08:32:08 -05:00
|
|
|
|
// Fallback for unknown types
|
|
|
|
|
|
dataTemplate = Default;
|
2025-07-09 14:53:47 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return dataTemplate;
|
2025-05-28 14:35:26 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|