Navigation.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using System;
  2. using System.Diagnostics.Tracing;
  3. using Avalonia.Layout;
  4. using CommunityToolkit.Mvvm.ComponentModel;
  5. using DialogHostAvalonia;
  6. using InABox.Avalonia.Components;
  7. using InABox.Avalonia.Router;
  8. namespace InABox.Avalonia;
  9. public interface IViewModelBase
  10. {
  11. Task Activate();
  12. Task Deactivate();
  13. bool BackButtonVisible { get; set; }
  14. bool ProgressVisible { get; set; }
  15. AvaloniaMenuItemCollection PrimaryMenu { get; set; }
  16. AvaloniaMenuItemCollection SecondaryMenu { get; set; }
  17. }
  18. public interface IPopupViewModel
  19. {
  20. bool IsClosed { get; }
  21. }
  22. /// <summary>
  23. /// Indicates that this view model can be a module or a popup.
  24. /// </summary>
  25. public interface IDualFunctionViewModel : IPopupViewModel, IViewModelBase
  26. {
  27. bool IsPopup { get; set; }
  28. }
  29. public interface IAlignedPopup
  30. {
  31. HorizontalAlignment HorizontalAlignment { get; }
  32. VerticalAlignment VerticalAlignment { get; }
  33. }
  34. public interface IPopupViewModel<TResult> : IPopupViewModel
  35. {
  36. TResult? GetResult();
  37. }
  38. public static class Navigation
  39. {
  40. private static readonly HistoryRouter<IViewModelBase> _router;
  41. static Navigation()
  42. {
  43. _router = new HistoryRouter<IViewModelBase>(x => Activator.CreateInstance(x) as IViewModelBase);
  44. _router.CurrentViewModelChanging += (@base, direction) => CurrentViewModelChanging?.Invoke(@base, direction);
  45. _router.CurrentViewModelChanged += @base => CurrentViewModelChanged?.Invoke(@base);
  46. }
  47. public static void Back()
  48. {
  49. _router.Back();
  50. }
  51. public static void Navigate<T>(Action<T>? configure = null) where T : IViewModelBase
  52. {
  53. _router.GoTo<T>(configure);
  54. }
  55. public static async Task<object?> Popup<T>(Action<T>? configure = null, bool canTapAway = true)
  56. where T : IViewModelBase, IPopupViewModel
  57. {
  58. var viewModel = _router.InstantiateViewModel<T>(configure);
  59. return await Popup(viewModel, canTapAway);
  60. }
  61. public static async Task<object?> Popup<T>(T viewModel, bool canTapAway = true)
  62. where T : IViewModelBase, IPopupViewModel
  63. {
  64. if (viewModel is IDualFunctionViewModel dualFunction)
  65. {
  66. dualFunction.IsPopup = true;
  67. }
  68. await viewModel.Activate();
  69. var _result = await DialogHostAvalonia.DialogHost.Show(viewModel, (object sender, DialogClosingEventArgs eventArgs) =>
  70. {
  71. if(!canTapAway && !viewModel.IsClosed)
  72. {
  73. eventArgs.Cancel();
  74. }
  75. });
  76. await viewModel.Deactivate();
  77. return _result;
  78. }
  79. public static async Task<TResult?> Popup<T, TResult>(Action<T>? configure = null, bool canTapAway = true)
  80. where T : IViewModelBase, IPopupViewModel<TResult>
  81. {
  82. var viewModel = _router.InstantiateViewModel<T>(configure);
  83. return await Popup<T, TResult>(viewModel, canTapAway);
  84. }
  85. public static async Task<TResult?> Popup<T, TResult>(T viewModel, bool canTapAway = true)
  86. where T : IViewModelBase, IPopupViewModel<TResult>
  87. {
  88. if (viewModel is IDualFunctionViewModel dualFunction)
  89. {
  90. dualFunction.IsPopup = true;
  91. }
  92. await viewModel.Activate();
  93. var _result = await DialogHostAvalonia.DialogHost.Show(viewModel, (object sender, DialogClosingEventArgs eventArgs) =>
  94. {
  95. if(!canTapAway && !viewModel.IsClosed)
  96. {
  97. eventArgs.Cancel();
  98. }
  99. });
  100. await viewModel.Deactivate();
  101. return viewModel.GetResult();
  102. }
  103. public static void Reset<T>(Action<T>? configure = null) where T : IViewModelBase
  104. {
  105. _router.Reset<T>(configure);
  106. }
  107. public static event Action<IViewModelBase, RouterDirection>? CurrentViewModelChanging;
  108. public static event Action<IViewModelBase>? CurrentViewModelChanged;
  109. }
  110. public class BasePopupViewModel<TResult> : ObservableObject, IPopupViewModel<TResult?>, IViewModelBase
  111. {
  112. #region IPopupViewModel
  113. public bool IsClosed { get; private set; }
  114. protected TResult? _result;
  115. public TResult? GetResult()
  116. {
  117. return _result;
  118. }
  119. public void Close(TResult? result)
  120. {
  121. _result = result;
  122. IsClosed = true;
  123. DialogHost.GetDialogSession(null)?.Close();
  124. }
  125. #endregion
  126. #region IViewModel
  127. public bool BackButtonVisible { get; set; }
  128. public bool ProgressVisible { get; set; }
  129. public AvaloniaMenuItemCollection PrimaryMenu { get; set; } = new();
  130. public AvaloniaMenuItemCollection SecondaryMenu { get; set; } = new();
  131. public Task Activate()
  132. {
  133. return Task.CompletedTask;
  134. }
  135. public Task Deactivate()
  136. {
  137. return Task.CompletedTask;
  138. }
  139. #endregion
  140. }