From ce9bd1e67e07e6fe74bb44f47b8d74cd393d6e27 Mon Sep 17 00:00:00 2001 From: Yu Leng Date: Mon, 8 Dec 2025 14:01:18 +0800 Subject: [PATCH] Refactor: Replace custom RelayCommand with CommunityToolkit Replaced the custom RelayCommand implementation with the [RelayCommand] attribute from the CommunityToolkit.Mvvm library to simplify command creation and reduce boilerplate code. - Removed RelayCommand and RelayCommand classes. - Added CommunityToolkit.Mvvm package to the project. - Updated MainViewModel and MonitorViewModel to use [RelayCommand] for command generation. - Cleaned up unused imports related to the removed RelayCommand. This change improves maintainability and aligns the project with modern MVVM practices. --- .../PowerDisplay/Commands/RelayCommand.cs | 109 ------------------ .../PowerDisplay/PowerDisplay.csproj | 1 + .../PowerDisplay/ViewModels/MainViewModel.cs | 22 ++-- .../ViewModels/MonitorViewModel.cs | 24 ++-- 4 files changed, 28 insertions(+), 128 deletions(-) delete mode 100644 src/modules/powerdisplay/PowerDisplay/Commands/RelayCommand.cs diff --git a/src/modules/powerdisplay/PowerDisplay/Commands/RelayCommand.cs b/src/modules/powerdisplay/PowerDisplay/Commands/RelayCommand.cs deleted file mode 100644 index 6ac8ab4ce2..0000000000 --- a/src/modules/powerdisplay/PowerDisplay/Commands/RelayCommand.cs +++ /dev/null @@ -1,109 +0,0 @@ -// 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.Windows.Input; -using ManagedCommon; - -namespace PowerDisplay.Commands -{ - /// - /// Basic relay command implementation for parameterless actions - /// - public partial class RelayCommand : ICommand - { - private readonly Action _execute; - private readonly Func? _canExecute; - - public RelayCommand(Action execute, Func? canExecute = null) - { - _execute = execute ?? throw new ArgumentNullException(nameof(execute)); - _canExecute = canExecute; - } - -#pragma warning disable CS0067 // Event is never used - required by ICommand interface - public event EventHandler? CanExecuteChanged; -#pragma warning restore CS0067 - - public bool CanExecute(object? parameter) - { - if (_canExecute == null) - { - return true; - } - - try - { - return _canExecute.Invoke(); - } - catch (Exception ex) - { - Logger.LogError($"CanExecute failed: {ex.Message}"); - return false; - } - } - - public void Execute(object? parameter) - { - try - { - _execute(); - } - catch (Exception ex) - { - Logger.LogError($"Command execution failed: {ex.Message}"); - } - } - } - - /// - /// Generic relay command implementation for parameterized actions - /// - /// Type of the command parameter - public partial class RelayCommand : ICommand - { - private readonly Action _execute; - private readonly Func? _canExecute; - - public RelayCommand(Action execute, Func? canExecute = null) - { - _execute = execute ?? throw new ArgumentNullException(nameof(execute)); - _canExecute = canExecute; - } - -#pragma warning disable CS0067 // Event is never used - required by ICommand interface - public event EventHandler? CanExecuteChanged; -#pragma warning restore CS0067 - - public bool CanExecute(object? parameter) - { - if (_canExecute == null) - { - return true; - } - - try - { - return _canExecute.Invoke((T?)parameter); - } - catch (Exception ex) - { - Logger.LogError($"CanExecute failed: {ex.Message}"); - return false; - } - } - - public void Execute(object? parameter) - { - try - { - _execute((T?)parameter); - } - catch (Exception ex) - { - Logger.LogError($"Command execution failed: {ex.Message}"); - } - } - } -} diff --git a/src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj b/src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj index cc00c45d39..2cbf01f08f 100644 --- a/src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj +++ b/src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj @@ -59,6 +59,7 @@ + all diff --git a/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs b/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs index 734269008d..6015881dd7 100644 --- a/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs +++ b/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs @@ -9,12 +9,12 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; -using System.Windows.Input; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.Input; using ManagedCommon; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI.Dispatching; using Microsoft.UI.Windowing; -using PowerDisplay.Commands; using PowerDisplay.Common.Models; using PowerDisplay.Common.Services; using PowerDisplay.Helpers; @@ -168,17 +168,20 @@ public partial class MainViewModel : INotifyPropertyChanged, IDisposable /// public bool IsInteractionEnabled => !IsLoading && !IsScanning; - public ICommand RefreshCommand => new RelayCommand(async () => await RefreshMonitorsAsync()); + [RelayCommand] + private async Task RefreshAsync() => await RefreshMonitorsAsync(); - public ICommand SetAllBrightnessCommand => new RelayCommand(async (brightness) => + [RelayCommand] + private async Task SetAllBrightness(int? brightness) { if (brightness.HasValue) { await SetAllBrightnessAsync(brightness.Value); } - }); + } - public ICommand IdentifyMonitorsCommand => new RelayCommand(() => + [RelayCommand] + private void IdentifyMonitors() { Logger.LogInfo("Identify monitors feature triggered"); @@ -217,16 +220,17 @@ public partial class MainViewModel : INotifyPropertyChanged, IDisposable Logger.LogError($"Failed to identify monitors: {ex.Message}"); Logger.LogError($"Stack trace: {ex.StackTrace}"); } - }); + } - public ICommand ApplyProfileCommand => new RelayCommand(async profile => + [RelayCommand] + private async Task ApplyProfile(PowerDisplayProfile? profile) { if (profile != null && profile.IsValid()) { Logger.LogInfo($"[Profile] Applying profile '{profile.Name}' from quick apply"); await ApplyProfileAsync(profile.Name, profile.MonitorSettings); } - }); + } public event PropertyChangedEventHandler? PropertyChanged; diff --git a/src/modules/powerdisplay/PowerDisplay/ViewModels/MonitorViewModel.cs b/src/modules/powerdisplay/PowerDisplay/ViewModels/MonitorViewModel.cs index 86838a8b19..2684e37c30 100644 --- a/src/modules/powerdisplay/PowerDisplay/ViewModels/MonitorViewModel.cs +++ b/src/modules/powerdisplay/PowerDisplay/ViewModels/MonitorViewModel.cs @@ -9,10 +9,10 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -using System.Windows.Input; +using CommunityToolkit.Mvvm.Input; using ManagedCommon; using Microsoft.UI.Xaml; -using PowerDisplay.Commands; + using PowerDisplay.Common.Models; using PowerDisplay.Common.Utils; using PowerDisplay.Configuration; @@ -574,13 +574,14 @@ public partial class MonitorViewModel : INotifyPropertyChanged, IDisposable /// /// Command to set input source /// - public ICommand SetInputSourceCommand => new RelayCommand(async (source) => + [RelayCommand] + private async Task SetInputSource(int? source) { if (source.HasValue) { await SetInputSourceAsync(source.Value); } - }); + } public int Contrast { @@ -618,29 +619,32 @@ public partial class MonitorViewModel : INotifyPropertyChanged, IDisposable } } - public ICommand SetBrightnessCommand => new RelayCommand((brightness) => + [RelayCommand] + private void SetBrightness(int? brightness) { if (brightness.HasValue) { Brightness = brightness.Value; } - }); + } - public ICommand SetContrastCommand => new RelayCommand((contrast) => + [RelayCommand] + private void SetContrast(int? contrast) { if (contrast.HasValue) { Contrast = contrast.Value; } - }); + } - public ICommand SetVolumeCommand => new RelayCommand((volume) => + [RelayCommand] + private void SetVolume(int? volume) { if (volume.HasValue) { Volume = volume.Value; } - }); + } public int ContrastPercent {