NavigationPageMvvmViewModels.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. using System.Collections.Generic;
  2. using System.Threading.Tasks;
  3. using Avalonia.Media;
  4. using MiniMvvm;
  5. namespace ControlCatalog.Pages
  6. {
  7. public sealed class NavigationPageMvvmShellViewModel : ViewModelBase
  8. {
  9. private readonly ISampleNavigationService _navigationService;
  10. private string _currentPageHeader = "Not initialized";
  11. private string _lastAction = "Waiting for first load";
  12. private int _navigationDepth;
  13. private ProjectCardViewModel? _selectedProject;
  14. internal NavigationPageMvvmShellViewModel(ISampleNavigationService navigationService)
  15. {
  16. _navigationService = navigationService;
  17. _navigationService.StateChanged += OnStateChanged;
  18. Workspace = new WorkspaceViewModel(CreateProjects(navigationService));
  19. SelectedProject = Workspace.Projects[0];
  20. OpenSelectedProjectCommand = MiniCommand.CreateFromTask(OpenSelectedProjectAsync);
  21. GoBackCommand = MiniCommand.CreateFromTask(_navigationService.GoBackAsync);
  22. PopToRootCommand = MiniCommand.CreateFromTask(_navigationService.PopToRootAsync);
  23. }
  24. internal WorkspaceViewModel Workspace { get; }
  25. public IReadOnlyList<ProjectCardViewModel> Projects => Workspace.Projects;
  26. public MiniCommand OpenSelectedProjectCommand { get; }
  27. public MiniCommand GoBackCommand { get; }
  28. public MiniCommand PopToRootCommand { get; }
  29. public string CurrentPageHeader
  30. {
  31. get => _currentPageHeader;
  32. set => this.RaiseAndSetIfChanged(ref _currentPageHeader, value);
  33. }
  34. public int NavigationDepth
  35. {
  36. get => _navigationDepth;
  37. set => this.RaiseAndSetIfChanged(ref _navigationDepth, value);
  38. }
  39. public string LastAction
  40. {
  41. get => _lastAction;
  42. set => this.RaiseAndSetIfChanged(ref _lastAction, value);
  43. }
  44. public ProjectCardViewModel? SelectedProject
  45. {
  46. get => _selectedProject;
  47. set => this.RaiseAndSetIfChanged(ref _selectedProject, value);
  48. }
  49. public Task InitializeAsync() => _navigationService.NavigateToAsync(Workspace);
  50. private async Task OpenSelectedProjectAsync()
  51. {
  52. if (SelectedProject == null)
  53. return;
  54. await SelectedProject.OpenCommandAsync();
  55. }
  56. private void OnStateChanged(object? sender, NavigationStateChangedEventArgs e)
  57. {
  58. CurrentPageHeader = e.CurrentPageHeader;
  59. NavigationDepth = e.NavigationDepth;
  60. LastAction = e.LastAction;
  61. }
  62. private static IReadOnlyList<ProjectCardViewModel> CreateProjects(ISampleNavigationService navigationService) =>
  63. new[]
  64. {
  65. new ProjectCardViewModel(
  66. "Release Radar",
  67. "Marta Collins",
  68. "Ready for QA",
  69. "Coordinate the 11.0 release checklist and lock down the final regression window.",
  70. "Freeze build on Friday",
  71. Color.Parse("#0063B1"),
  72. navigationService,
  73. new[]
  74. {
  75. "Release notes draft updated with accessibility fixes.",
  76. "Package validation finished for desktop artifacts.",
  77. "Remaining task, confirm browser smoke test coverage."
  78. }),
  79. new ProjectCardViewModel(
  80. "Support Console",
  81. "Jae Kim",
  82. "Active Sprint",
  83. "Consolidate customer incidents into a triage board and route them to platform owners.",
  84. "Triage review in 2 hours",
  85. Color.Parse("#0F7B0F"),
  86. navigationService,
  87. new[]
  88. {
  89. "Five customer reports grouped under input routing.",
  90. "Hotfix candidate approved for preview branch.",
  91. "Awaiting macOS verification on native embed scenarios."
  92. }),
  93. new ProjectCardViewModel(
  94. "Docs Refresh",
  95. "Anika Patel",
  96. "Needs Review",
  97. "Refresh navigation samples and walkthrough docs so the gallery matches the current API.",
  98. "Sample review tomorrow",
  99. Color.Parse("#8E562E"),
  100. navigationService,
  101. new[]
  102. {
  103. "NavigationPage sample matrix reviewed with design.",
  104. "MVVM walkthrough draft linked from the docs backlog.",
  105. "Outstanding task, capture one more screenshot for drawer navigation."
  106. }),
  107. };
  108. }
  109. internal sealed class WorkspaceViewModel : ViewModelBase
  110. {
  111. public WorkspaceViewModel(IReadOnlyList<ProjectCardViewModel> projects)
  112. {
  113. Projects = projects;
  114. }
  115. public string Title => "Team Workspace";
  116. public string Description =>
  117. "Each card is a project view model with its own command. The command asks ISampleNavigationService to navigate with the next view model, and SamplePageFactory resolves the matching ContentPage.";
  118. public IReadOnlyList<ProjectCardViewModel> Projects { get; }
  119. }
  120. public sealed class ProjectCardViewModel : ViewModelBase
  121. {
  122. private readonly ISampleNavigationService _navigationService;
  123. internal ProjectCardViewModel(
  124. string name,
  125. string owner,
  126. string status,
  127. string summary,
  128. string nextMilestone,
  129. Color accentColor,
  130. ISampleNavigationService navigationService,
  131. IReadOnlyList<string> activityItems)
  132. {
  133. Name = name;
  134. Owner = owner;
  135. Status = status;
  136. Summary = summary;
  137. NextMilestone = nextMilestone;
  138. AccentColor = accentColor;
  139. ActivityItems = activityItems;
  140. _navigationService = navigationService;
  141. OpenCommand = MiniCommand.CreateFromTask(OpenCommandAsync);
  142. }
  143. public string Name { get; }
  144. public string Owner { get; }
  145. public string Status { get; }
  146. public string Summary { get; }
  147. public string NextMilestone { get; }
  148. public Color AccentColor { get; }
  149. public IReadOnlyList<string> ActivityItems { get; }
  150. public MiniCommand OpenCommand { get; }
  151. public Task OpenCommandAsync()
  152. {
  153. return _navigationService.NavigateToAsync(new ProjectDetailViewModel(this, _navigationService));
  154. }
  155. }
  156. internal sealed class ProjectDetailViewModel : ViewModelBase
  157. {
  158. private readonly ProjectCardViewModel _project;
  159. private readonly ISampleNavigationService _navigationService;
  160. public ProjectDetailViewModel(ProjectCardViewModel project, ISampleNavigationService navigationService)
  161. {
  162. _project = project;
  163. _navigationService = navigationService;
  164. OpenActivityCommand = MiniCommand.CreateFromTask(OpenActivityAsync);
  165. }
  166. public string Name => _project.Name;
  167. public string Owner => _project.Owner;
  168. public string Status => _project.Status;
  169. public string Summary => _project.Summary;
  170. public string NextMilestone => _project.NextMilestone;
  171. public Color AccentColor => _project.AccentColor;
  172. public MiniCommand OpenActivityCommand { get; }
  173. private Task OpenActivityAsync()
  174. {
  175. return _navigationService.NavigateToAsync(new ProjectActivityViewModel(_project));
  176. }
  177. }
  178. internal sealed class ProjectActivityViewModel : ViewModelBase
  179. {
  180. public ProjectActivityViewModel(ProjectCardViewModel project)
  181. {
  182. Name = project.Name;
  183. AccentColor = project.AccentColor;
  184. Items = project.ActivityItems;
  185. }
  186. public string Name { get; }
  187. public Color AccentColor { get; }
  188. public IReadOnlyList<string> Items { get; }
  189. }
  190. }