mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 04:37:30 +02:00
CmdPal: Fix FiltersViewModel binding (#42467)
## Summary of the Pull Request This PR resolves crashes on pages with filters, such as Windows Terminal profiles or Windows Services, when compiled with trimming/AOT. It removes runtime binding from the FiltersDropDown control, effectively preventing crashes caused by trimming/AOT dropping binding metadata for FilterItemViewModel. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #42428 - [x] Closes: #42482 - [x] Related to: #42458 - [ ] **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 Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
@@ -2,8 +2,10 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||||
using Microsoft.CommandPalette.Extensions;
|
using Microsoft.CommandPalette.Extensions;
|
||||||
|
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.Core.ViewModels;
|
namespace Microsoft.CmdPal.Core.ViewModels;
|
||||||
|
|
||||||
@@ -13,6 +15,8 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
|
|||||||
|
|
||||||
public string CurrentFilterId { get; private set; } = string.Empty;
|
public string CurrentFilterId { get; private set; } = string.Empty;
|
||||||
|
|
||||||
|
public IFilterItemViewModel? CurrentFilter { get; private set; }
|
||||||
|
|
||||||
public IFilterItemViewModel[] Filters { get; private set; } = [];
|
public IFilterItemViewModel[] Filters { get; private set; } = [];
|
||||||
|
|
||||||
public bool ShouldShowFilters => Filters.Length > 0;
|
public bool ShouldShowFilters => Filters.Length > 0;
|
||||||
@@ -30,11 +34,13 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
|
|||||||
if (_filtersModel.Unsafe is not null)
|
if (_filtersModel.Unsafe is not null)
|
||||||
{
|
{
|
||||||
var filters = _filtersModel.Unsafe.GetFilters();
|
var filters = _filtersModel.Unsafe.GetFilters();
|
||||||
Filters = BuildFilters(filters ?? []);
|
var currentFilterId = _filtersModel.Unsafe.CurrentFilterId ?? string.Empty;
|
||||||
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters));
|
|
||||||
|
|
||||||
CurrentFilterId = _filtersModel.Unsafe.CurrentFilterId ?? string.Empty;
|
var result = BuildFilters(filters ?? [], currentFilterId);
|
||||||
UpdateProperty(nameof(CurrentFilterId));
|
Filters = result.Items;
|
||||||
|
CurrentFilterId = currentFilterId;
|
||||||
|
CurrentFilter = result.Selected;
|
||||||
|
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters), nameof(CurrentFilterId), nameof(CurrentFilter));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -45,27 +51,48 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
Filters = [];
|
Filters = [];
|
||||||
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters));
|
|
||||||
|
|
||||||
CurrentFilterId = string.Empty;
|
CurrentFilterId = string.Empty;
|
||||||
UpdateProperty(nameof(CurrentFilterId));
|
CurrentFilter = null;
|
||||||
|
UpdateProperty(nameof(Filters), nameof(ShouldShowFilters), nameof(CurrentFilterId), nameof(CurrentFilter));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IFilterItemViewModel[] BuildFilters(IFilterItem[] filters)
|
private (IFilterItemViewModel[] Items, IFilterItemViewModel? Selected) BuildFilters(IFilterItem[] filters, string currentFilterId)
|
||||||
{
|
{
|
||||||
return [..filters.Select<IFilterItem, IFilterItemViewModel>(filter =>
|
if (filters is null || filters.Length == 0)
|
||||||
|
{
|
||||||
|
return ([], null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = new List<IFilterItemViewModel>(filters.Length);
|
||||||
|
FilterItemViewModel? firstFilterItem = null;
|
||||||
|
FilterItemViewModel? selectedFilterItem = null;
|
||||||
|
|
||||||
|
foreach (var filter in filters)
|
||||||
{
|
{
|
||||||
if (filter is IFilter filterItem)
|
if (filter is IFilter filterItem)
|
||||||
{
|
{
|
||||||
var filterItemViewModel = new FilterItemViewModel(filterItem!, PageContext);
|
var filterItemViewModel = new FilterItemViewModel(filterItem, PageContext);
|
||||||
filterItemViewModel.InitializeProperties();
|
filterItemViewModel.InitializeProperties();
|
||||||
return filterItemViewModel;
|
|
||||||
|
if (firstFilterItem is null)
|
||||||
|
{
|
||||||
|
firstFilterItem = filterItemViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedFilterItem is null && filterItemViewModel.Id == currentFilterId)
|
||||||
|
{
|
||||||
|
selectedFilterItem = filterItemViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
items.Add(filterItemViewModel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new SeparatorViewModel();
|
items.Add(new SeparatorViewModel());
|
||||||
}
|
}
|
||||||
})];
|
}
|
||||||
|
|
||||||
|
return (items.ToArray(), selectedFilterItem ?? firstFilterItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SafeCleanup()
|
public override void SafeCleanup()
|
||||||
|
|||||||
@@ -74,8 +74,7 @@
|
|||||||
ItemsSource="{x:Bind ViewModel.Filters, Mode=OneWay}"
|
ItemsSource="{x:Bind ViewModel.Filters, Mode=OneWay}"
|
||||||
PlaceholderText="Filters"
|
PlaceholderText="Filters"
|
||||||
PreviewKeyDown="FiltersComboBox_PreviewKeyDown"
|
PreviewKeyDown="FiltersComboBox_PreviewKeyDown"
|
||||||
SelectedValue="{x:Bind ViewModel.CurrentFilterId, Mode=OneWay}"
|
SelectedValue="{x:Bind ViewModel.CurrentFilter, Mode=OneWay}"
|
||||||
SelectedValuePath="Id"
|
|
||||||
SelectionChanged="FiltersComboBox_SelectionChanged"
|
SelectionChanged="FiltersComboBox_SelectionChanged"
|
||||||
Style="{StaticResource ComboBoxStyle}"
|
Style="{StaticResource ComboBoxStyle}"
|
||||||
Visibility="{x:Bind ViewModel.ShouldShowFilters, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
Visibility="{x:Bind ViewModel.ShouldShowFilters, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||||
|
|||||||
Reference in New Issue
Block a user