Skip to content

Commit cece874

Browse files
sharpninjaCopilot
andcommitted
refactor: convert parameterless commands to CqrsRelayCommand<T> properties
- MainWindowViewModel: 5 [RelayCommand] methods → CqrsRelayCommand<bool> properties (CloseRequestDetails, OpenPreviewInBrowser, ToggleShowRawMarkdown, OpenAgentConfig, OpenPromptTemplates) - ChatWindowViewModel: 2 [RelayCommand] methods → CqrsRelayCommand<ChatFileOpenResult> (OpenAgentConfig, OpenPromptTemplates) - Added InitializeCqrsCommands() in MWVM called after Dispatcher is assigned - Parameterized commands kept as [RelayCommand] (CqrsRelayCommand doesn't support AXAML params) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent f22e4db commit cece874

2 files changed

Lines changed: 25 additions & 22 deletions

File tree

src/McpServerManager.Core/ViewModels/ChatWindowViewModel.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using CommunityToolkit.Mvvm.ComponentModel;
66
using CommunityToolkit.Mvvm.Input;
77
using McpServer.Cqrs;
8+
using McpServer.Cqrs.Mvvm;
89
using McpServerManager.Core.Commands;
910
using McpServerManager.Core.Models;
1011
using McpServerManager.Core.Services;
@@ -38,6 +39,9 @@ public partial class ChatWindowViewModel : ViewModelBase
3839
[ObservableProperty]
3940
private ObservableCollection<PromptTemplate> _promptTemplates = new();
4041

42+
public CqrsRelayCommand<ChatFileOpenResult> OpenAgentConfigCommand { get; }
43+
public CqrsRelayCommand<ChatFileOpenResult> OpenPromptTemplatesCommand { get; }
44+
4145
public ChatWindowViewModel(
4246
McpServer.Cqrs.Dispatcher dispatcher,
4347
Func<string> getContext,
@@ -48,23 +52,14 @@ public ChatWindowViewModel(
4852
_getContext = getContext ?? (() => "");
4953
_initialModelFromConfig = initialModelFromConfig;
5054
_onModelChanged = onModelChanged;
55+
56+
OpenAgentConfigCommand = new CqrsRelayCommand<ChatFileOpenResult>(_dispatcher, () => new ChatOpenAgentConfigCommand());
57+
OpenPromptTemplatesCommand = new CqrsRelayCommand<ChatFileOpenResult>(_dispatcher, () => new ChatOpenPromptTemplatesCommand());
5158
}
5259

5360
/// <summary>Parameterless constructor for design-time only.</summary>
5461
public ChatWindowViewModel() : this(null!, () => "", null, null) { }
5562

56-
[RelayCommand]
57-
private async Task OpenAgentConfig()
58-
{
59-
_ = await _dispatcher.SendAsync(new ChatOpenAgentConfigCommand()).ConfigureAwait(true);
60-
}
61-
62-
[RelayCommand]
63-
private async Task OpenPromptTemplates()
64-
{
65-
_ = await _dispatcher.SendAsync(new ChatOpenPromptTemplatesCommand()).ConfigureAwait(true);
66-
}
67-
6863
/// <summary>Loads prompt templates from agent config. Call when the chat window is opened.</summary>
6964
public void LoadPrompts() => _ = LoadPromptsAsync();
7065

src/McpServerManager.Core/ViewModels/MainWindowViewModel.cs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using CommunityToolkit.Mvvm.Input;
2020
using Microsoft.Extensions.Logging;
2121
using McpServer.Client;
22+
using McpServer.Cqrs.Mvvm;
2223
using McpServerManager.Core.Converters;
2324
using McpServerManager.Core.Models;
2425
using McpServerManager.Core.Models.Json;
@@ -81,6 +82,13 @@ public partial class MainWindowViewModel : ViewModelBase, Commands.ICommandTarge
8182
/// <summary>Raised when the active workspace path changes. Child VMs subscribe to refresh reactively.</summary>
8283
public event Action<string>? WorkspacePathChanged;
8384

85+
// ── CqrsRelayCommand properties (parameterless CQRS dispatches) ──
86+
public CqrsRelayCommand<bool> CloseRequestDetailsCommand { get; private set; } = null!;
87+
public CqrsRelayCommand<bool> OpenPreviewInBrowserCommand { get; private set; } = null!;
88+
public CqrsRelayCommand<bool> ToggleShowRawMarkdownCommand { get; private set; } = null!;
89+
public CqrsRelayCommand<bool> OpenAgentConfigCommand { get; private set; } = null!;
90+
public CqrsRelayCommand<bool> OpenPromptTemplatesCommand { get; private set; } = null!;
91+
8492
/// <summary>ViewModel for the Todo tab. Created lazily on first access.</summary>
8593
public TodoListViewModel TodoViewModel => _todoViewModel ??= CreateTodoViewModel();
8694
private TodoListViewModel? _todoViewModel;
@@ -442,6 +450,7 @@ private void InitializeMcpEndpoint(string mcpBaseUrl, string? initialApiKey = nu
442450
ActiveWorkspacePath = _mcpClient.WorkspacePath ?? string.Empty
443451
});
444452
_dispatcher = _uiCoreRuntime.GetRequiredService<McpServer.Cqrs.Dispatcher>();
453+
InitializeCqrsCommands();
445454

446455
// Pre-populate the workspace picker with a placeholder.
447456
// No switch is triggered here — the real switch happens in LoadWorkspaceConnectionsAsync
@@ -471,6 +480,15 @@ private static string NormalizeMcpBaseUrl(string mcpBaseUrl)
471480
return uri.ToString().TrimEnd('/');
472481
}
473482

483+
private void InitializeCqrsCommands()
484+
{
485+
CloseRequestDetailsCommand = new CqrsRelayCommand<bool>(_dispatcher, () => new Commands.CloseRequestDetailsCommand());
486+
OpenPreviewInBrowserCommand = new CqrsRelayCommand<bool>(_dispatcher, () => new Commands.OpenPreviewInBrowserCommand());
487+
ToggleShowRawMarkdownCommand = new CqrsRelayCommand<bool>(_dispatcher, () => new Commands.ToggleShowRawMarkdownCommand());
488+
OpenAgentConfigCommand = new CqrsRelayCommand<bool>(_dispatcher, () => new Commands.OpenAgentConfigCommand());
489+
OpenPromptTemplatesCommand = new CqrsRelayCommand<bool>(_dispatcher, () => new Commands.OpenPromptTemplatesCommand());
490+
}
491+
474492
private void ApplyActiveMcpBaseUrl(string mcpBaseUrl, string? mcpApiKey = null, string? workspaceRootPath = null)
475493
{
476494
_activeMcpBaseUrl = NormalizeMcpBaseUrl(mcpBaseUrl);
@@ -1905,8 +1923,6 @@ public void SelectSearchEntryInternal(SearchableEntry entry)
19051923
SelectedSearchEntry = entry;
19061924
}
19071925

1908-
[RelayCommand]
1909-
private void CloseRequestDetails() => _ = _dispatcher.SendAsync(new Commands.CloseRequestDetailsCommand());
19101926

19111927
public void CloseRequestDetailsInternal()
19121928
{
@@ -2683,8 +2699,6 @@ private void OpenHtmlInDefaultBrowser(string htmlFilePath)
26832699
}
26842700
}
26852701

2686-
[RelayCommand]
2687-
private void OpenPreviewInBrowser() => _ = _dispatcher.SendAsync(new Commands.OpenPreviewInBrowserCommand());
26882702

26892703
public void OpenPreviewInBrowserInternal()
26902704
{
@@ -2696,25 +2710,19 @@ public void OpenPreviewInBrowserInternal()
26962710
SetStatus("HTML preview is disabled.");
26972711
}
26982712

2699-
[RelayCommand]
2700-
private void ToggleShowRawMarkdown() => _ = _dispatcher.SendAsync(new Commands.ToggleShowRawMarkdownCommand());
27012713

27022714
public void ToggleShowRawMarkdownInternal()
27032715
{
27042716
ShowMarkdownAsRawText = !ShowMarkdownAsRawText;
27052717
}
27062718

2707-
[RelayCommand]
2708-
private void OpenAgentConfig() => _ = _dispatcher.SendAsync(new Commands.OpenAgentConfigCommand());
27092719

27102720
public void OpenAgentConfigInternal()
27112721
{
27122722
AgentConfigIo.EnsureExists();
27132723
OpenFileInDefaultEditor(AgentConfigIo.GetFilePath(), "config");
27142724
}
27152725

2716-
[RelayCommand]
2717-
private void OpenPromptTemplates() => _ = _dispatcher.SendAsync(new Commands.OpenPromptTemplatesCommand());
27182726

27192727
public void OpenPromptTemplatesInternal()
27202728
{

0 commit comments

Comments
 (0)