LoginView.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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 readonly CompositeDisposable _disposable = new ();
  10. public LoginView (LoginViewModel viewModel)
  11. {
  12. Title = $"Reactive Extensions Example - {Application.QuitKey} to Exit";
  13. ViewModel = viewModel;
  14. Label usernameLengthLabel = UsernameLengthLabel (TitleLabel ());
  15. TextField usernameInput = UsernameInput (usernameLengthLabel);
  16. Label passwordLengthLabel = PasswordLengthLabel (usernameLengthLabel);
  17. TextField passwordInput = PasswordInput (passwordLengthLabel);
  18. Label validationLabel = ValidationLabel (passwordInput);
  19. Button loginButton = LoginButton (validationLabel);
  20. Button clearButton = ClearButton (loginButton);
  21. LoginProgressLabel (clearButton);
  22. }
  23. public LoginViewModel ViewModel { get; set; }
  24. object IViewFor.ViewModel
  25. {
  26. get => ViewModel;
  27. set => ViewModel = (LoginViewModel)value;
  28. }
  29. protected override void Dispose (bool disposing)
  30. {
  31. _disposable.Dispose ();
  32. base.Dispose (disposing);
  33. }
  34. private Button ClearButton (View previous)
  35. {
  36. var clearButton = new Button
  37. {
  38. X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Text = "_Clear"
  39. };
  40. clearButton
  41. .Events ()
  42. .Accept
  43. .InvokeCommand (ViewModel, x => x.Clear)
  44. .DisposeWith (_disposable);
  45. Add (clearButton);
  46. return clearButton;
  47. }
  48. private Button LoginButton (View previous)
  49. {
  50. var loginButton = new Button
  51. {
  52. X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Text = "_Login"
  53. };
  54. loginButton
  55. .Events ()
  56. .Accept
  57. .InvokeCommand (ViewModel, x => x.Login)
  58. .DisposeWith (_disposable);
  59. Add (loginButton);
  60. return loginButton;
  61. }
  62. private Label LoginProgressLabel (View previous)
  63. {
  64. var progress = "Logging in...";
  65. var idle = "Press 'Login' to log in.";
  66. var loginProgressLabel = new Label
  67. {
  68. X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Width = 40, Height = 1, Text = idle
  69. };
  70. ViewModel
  71. .WhenAnyObservable (x => x.Login.IsExecuting)
  72. .Select (executing => executing ? progress : idle)
  73. .ObserveOn (RxApp.MainThreadScheduler)
  74. .BindTo (loginProgressLabel, x => x.Text)
  75. .DisposeWith (_disposable);
  76. Add (loginProgressLabel);
  77. return loginProgressLabel;
  78. }
  79. private TextField PasswordInput (View previous)
  80. {
  81. var passwordInput = new TextField
  82. {
  83. X = Pos.Right (previous) + 1, Y = Pos.Top (previous), Width = 40, Text = ViewModel.Password
  84. };
  85. ViewModel
  86. .WhenAnyValue (x => x.Password)
  87. .BindTo (passwordInput, x => x.Text)
  88. .DisposeWith (_disposable);
  89. passwordInput
  90. .Events ()
  91. .TextChanged
  92. .Select (old => passwordInput.Text)
  93. .DistinctUntilChanged ()
  94. .BindTo (ViewModel, x => x.Password)
  95. .DisposeWith (_disposable);
  96. Add (passwordInput);
  97. return passwordInput;
  98. }
  99. private Label PasswordLengthLabel (View previous)
  100. {
  101. var passwordLengthLabel = new Label { X = Pos.Left (previous), Y = Pos.Top (previous) + 1, };
  102. ViewModel
  103. .WhenAnyValue (x => x.PasswordLength)
  104. .Select (length => $"_Password ({length} characters):")
  105. .BindTo (passwordLengthLabel, x => x.Text)
  106. .DisposeWith (_disposable);
  107. Add (passwordLengthLabel);
  108. return passwordLengthLabel;
  109. }
  110. private Label TitleLabel ()
  111. {
  112. var label = new Label { Text = "Login Form" };
  113. Add (label);
  114. return label;
  115. }
  116. private TextField UsernameInput (View previous)
  117. {
  118. var usernameInput = new TextField
  119. {
  120. X = Pos.Right (previous) + 1, Y = Pos.Top (previous), Width = 40, Text = ViewModel.Username
  121. };
  122. ViewModel
  123. .WhenAnyValue (x => x.Username)
  124. .BindTo (usernameInput, x => x.Text)
  125. .DisposeWith (_disposable);
  126. usernameInput
  127. .Events ()
  128. .TextChanged
  129. .Select (old => usernameInput.Text)
  130. .DistinctUntilChanged ()
  131. .BindTo (ViewModel, x => x.Username)
  132. .DisposeWith (_disposable);
  133. Add (usernameInput);
  134. return usernameInput;
  135. }
  136. private Label UsernameLengthLabel (View previous)
  137. {
  138. var usernameLengthLabel = new Label { X = Pos.Left (previous), Y = Pos.Top (previous) + 1 };
  139. ViewModel
  140. .WhenAnyValue (x => x.UsernameLength)
  141. .Select (length => $"_Username ({length} characters):")
  142. .BindTo (usernameLengthLabel, x => x.Text)
  143. .DisposeWith (_disposable);
  144. Add (usernameLengthLabel);
  145. return usernameLengthLabel;
  146. }
  147. private Label ValidationLabel (View previous)
  148. {
  149. var error = "Please enter a valid user name and password.";
  150. var success = "The input is valid!";
  151. var validationLabel = new Label
  152. {
  153. X = Pos.Left (previous), Y = Pos.Top (previous) + 1, Text = error
  154. };
  155. ViewModel
  156. .WhenAnyValue (x => x.IsValid)
  157. .Select (valid => valid ? success : error)
  158. .BindTo (validationLabel, x => x.Text)
  159. .DisposeWith (_disposable);
  160. ViewModel
  161. .WhenAnyValue (x => x.IsValid)
  162. .Select (valid => valid ? Colors.ColorSchemes ["Base"] : Colors.ColorSchemes ["Error"])
  163. .BindTo (validationLabel, x => x.ColorScheme)
  164. .DisposeWith (_disposable);
  165. Add (validationLabel);
  166. return validationLabel;
  167. }
  168. }