LoginView.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. using System.Reactive.Disposables;
  2. using System.Reactive.Linq;
  3. using ReactiveMarbles.ObservableEvents;
  4. using ReactiveUI;
  5. using Terminal.Gui;
  6. namespace ReactiveExample;
  7. public class LoginView : Window, IViewFor<LoginViewModel>
  8. {
  9. private const string SuccessMessage = "The input is valid!";
  10. private const string ErrorMessage = "Please enter a valid user name and password.";
  11. private const string ProgressMessage = "Logging in...";
  12. private const string IdleMessage = "Press 'Login' to log in.";
  13. private readonly CompositeDisposable _disposable = [];
  14. public LoginView (LoginViewModel viewModel)
  15. {
  16. Title = $"Reactive Extensions Example - {Application.QuitKey} to Exit";
  17. ViewModel = viewModel;
  18. var title = this.AddControl<Label> (x => x.Text = "Login Form");
  19. var unLengthLabel = title.AddControlAfter<Label> ((previous, unLength) =>
  20. {
  21. unLength.X = Pos.Left (previous);
  22. unLength.Y = Pos.Top (previous) + 1;
  23. ViewModel
  24. .WhenAnyValue (x => x.UsernameLength)
  25. .Select (length => $"_Username ({length} characters):")
  26. .BindTo (unLength, x => x.Text)
  27. .DisposeWith (_disposable);
  28. });
  29. unLengthLabel.AddControlAfter<TextField> ((previous, unInput) =>
  30. {
  31. unInput.X = Pos.Right (previous) + 1;
  32. unInput.Y = Pos.Top (previous);
  33. unInput.Width = 40;
  34. unInput.Text = ViewModel.Username;
  35. ViewModel
  36. .WhenAnyValue (x => x.Username)
  37. .BindTo (unInput, x => x.Text)
  38. .DisposeWith (_disposable);
  39. unInput
  40. .Events ()
  41. .TextChanged
  42. .Select (_ => unInput.Text)
  43. .DistinctUntilChanged ()
  44. .BindTo (ViewModel, x => x.Username)
  45. .DisposeWith (_disposable);
  46. });
  47. unLengthLabel.AddControlAfter<Label> ((previous, pwLength) =>
  48. {
  49. pwLength.X = Pos.Left (previous);
  50. pwLength.Y = Pos.Top (previous) + 1;
  51. ViewModel
  52. .WhenAnyValue (x => x.PasswordLength)
  53. .Select (length => $"_Password ({length} characters):")
  54. .BindTo (pwLength, x => x.Text)
  55. .DisposeWith (_disposable);
  56. })
  57. .AddControlAfter<TextField> ((previous, pwInput) =>
  58. {
  59. pwInput.X = Pos.Right (previous) + 1;
  60. pwInput.Y = Pos.Top (previous);
  61. pwInput.Width = 40;
  62. pwInput.Text = ViewModel.Password;
  63. ViewModel
  64. .WhenAnyValue (x => x.Password)
  65. .BindTo (pwInput, x => x.Text)
  66. .DisposeWith (_disposable);
  67. pwInput
  68. .Events ()
  69. .TextChanged
  70. .Select (_ => pwInput.Text)
  71. .DistinctUntilChanged ()
  72. .BindTo (ViewModel, x => x.Password)
  73. .DisposeWith (_disposable);
  74. })
  75. .AddControlAfter<Label> ((previous, validation) =>
  76. {
  77. validation.X = Pos.Left (previous);
  78. validation.Y = Pos.Top (previous) + 1;
  79. validation.Text = ErrorMessage;
  80. ViewModel
  81. .WhenAnyValue (x => x.IsValid)
  82. .Select (valid => valid ? SuccessMessage : ErrorMessage)
  83. .BindTo (validation, x => x.Text)
  84. .DisposeWith (_disposable);
  85. ViewModel
  86. .WhenAnyValue (x => x.IsValid)
  87. .Select (valid => valid ? Colors.ColorSchemes ["Base"] : Colors.ColorSchemes ["Error"])
  88. .BindTo (validation, x => x.ColorScheme)
  89. .DisposeWith (_disposable);
  90. })
  91. .AddControlAfter<Button> ((previous, login) =>
  92. {
  93. login.X = Pos.Left (previous);
  94. login.Y = Pos.Top (previous) + 1;
  95. login.Text = "_Login";
  96. login
  97. .Events ()
  98. .Accept
  99. .InvokeCommand (ViewModel, x => x.Login)
  100. .DisposeWith (_disposable);
  101. })
  102. .AddControlAfter<Button> ((previous, clear) =>
  103. {
  104. clear.X = Pos.Left (previous);
  105. clear.Y = Pos.Top (previous) + 1;
  106. clear.Text = "_Clear";
  107. clear
  108. .Events ()
  109. .Accept
  110. .InvokeCommand (ViewModel, x => x.ClearCommand)
  111. .DisposeWith (_disposable);
  112. })
  113. .AddControlAfter<Label> ((previous, progress) =>
  114. {
  115. progress.X = Pos.Left (previous);
  116. progress.Y = Pos.Top (previous) + 1;
  117. progress.Width = 40;
  118. progress.Height = 1;
  119. progress.Text = IdleMessage;
  120. ViewModel
  121. .WhenAnyObservable (x => x.Login.IsExecuting)
  122. .Select (executing => executing ? ProgressMessage : IdleMessage)
  123. .ObserveOn (RxApp.MainThreadScheduler)
  124. .BindTo (progress, x => x.Text)
  125. .DisposeWith (_disposable);
  126. });
  127. }
  128. public LoginViewModel ViewModel { get; set; }
  129. object IViewFor.ViewModel
  130. {
  131. get => ViewModel;
  132. set => ViewModel = (LoginViewModel)value;
  133. }
  134. protected override void Dispose (bool disposing)
  135. {
  136. _disposable.Dispose ();
  137. base.Dispose (disposing);
  138. }
  139. }