LoginView.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using System.Reactive.Disposables;
  2. using System.Reactive.Linq;
  3. using NStack;
  4. using ReactiveUI;
  5. using Terminal.Gui;
  6. namespace ReactiveExample {
  7. public class LoginView : Window, IViewFor<LoginViewModel> {
  8. readonly CompositeDisposable _disposable = new CompositeDisposable();
  9. public LoginView (LoginViewModel viewModel) : base("Reactive Extensions Example") {
  10. ViewModel = viewModel;
  11. this.StackPanel (new Label ("Login Form"))
  12. .Append (UsernameLengthLabel ())
  13. .Append (UsernameInput ())
  14. .Append (PasswordLengthLabel ())
  15. .Append (PasswordInput ())
  16. .Append (ValidationLabel ())
  17. .Append (LoginButton ())
  18. .Append (ClearButton ())
  19. .Append (LoginProgressLabel ());
  20. }
  21. public LoginViewModel ViewModel { get; set; }
  22. protected override void Dispose (bool disposing) {
  23. _disposable.Dispose ();
  24. base.Dispose (disposing);
  25. }
  26. TextField UsernameInput () {
  27. var usernameInput = new TextField (ViewModel.Username) { Width = 40 };
  28. ViewModel
  29. .WhenAnyValue (x => x.Username)
  30. .BindTo (usernameInput, x => x.Text)
  31. .DisposeWith (_disposable);
  32. usernameInput
  33. .Events ()
  34. .TextChanged
  35. .Select (old => usernameInput.Text)
  36. .DistinctUntilChanged ()
  37. .BindTo (ViewModel, x => x.Username)
  38. .DisposeWith (_disposable);
  39. return usernameInput;
  40. }
  41. Label UsernameLengthLabel () {
  42. var usernameLengthLabel = new Label { Width = 40 };
  43. ViewModel
  44. .WhenAnyValue (x => x.UsernameLength)
  45. .Select (length => ustring.Make ($"Username ({length} characters)"))
  46. .BindTo (usernameLengthLabel, x => x.Text)
  47. .DisposeWith (_disposable);
  48. return usernameLengthLabel;
  49. }
  50. TextField PasswordInput () {
  51. var passwordInput = new TextField (ViewModel.Password) { Width = 40 };
  52. ViewModel
  53. .WhenAnyValue (x => x.Password)
  54. .BindTo (passwordInput, x => x.Text)
  55. .DisposeWith (_disposable);
  56. passwordInput
  57. .Events ()
  58. .TextChanged
  59. .Select (old => passwordInput.Text)
  60. .DistinctUntilChanged ()
  61. .BindTo (ViewModel, x => x.Password)
  62. .DisposeWith (_disposable);
  63. return passwordInput;
  64. }
  65. Label PasswordLengthLabel () {
  66. var passwordLengthLabel = new Label { Width = 40 };
  67. ViewModel
  68. .WhenAnyValue (x => x.PasswordLength)
  69. .Select (length => ustring.Make ($"Password ({length} characters)"))
  70. .BindTo (passwordLengthLabel, x => x.Text)
  71. .DisposeWith (_disposable);
  72. return passwordLengthLabel;
  73. }
  74. Label ValidationLabel () {
  75. var error = ustring.Make("Please, enter user name and password.");
  76. var success = ustring.Make("The input is valid!");
  77. var validationLabel = new Label(error) { Width = 40 };
  78. ViewModel
  79. .WhenAnyValue (x => x.IsValid)
  80. .Select (valid => valid ? success : error)
  81. .BindTo (validationLabel, x => x.Text)
  82. .DisposeWith (_disposable);
  83. ViewModel
  84. .WhenAnyValue (x => x.IsValid)
  85. .Select (valid => valid ? Colors.Base : Colors.Error)
  86. .BindTo (validationLabel, x => x.ColorScheme)
  87. .DisposeWith (_disposable);
  88. return validationLabel;
  89. }
  90. Label LoginProgressLabel () {
  91. var progress = ustring.Make ("Logging in...");
  92. var idle = ustring.Make ("Press 'Login' to log in.");
  93. var loginProgressLabel = new Label(idle) { Width = 40 };
  94. ViewModel
  95. .WhenAnyObservable (x => x.Login.IsExecuting)
  96. .Select (executing => executing ? progress : idle)
  97. .BindTo (loginProgressLabel, x => x.Text)
  98. .DisposeWith (_disposable);
  99. return loginProgressLabel;
  100. }
  101. Button LoginButton () {
  102. var loginButton = new Button ("Login") { Width = 40 };
  103. loginButton
  104. .Events ()
  105. .Clicked
  106. .InvokeCommand (ViewModel, x => x.Login)
  107. .DisposeWith (_disposable);
  108. return loginButton;
  109. }
  110. Button ClearButton () {
  111. var clearButton = new Button("Clear") { Width = 40 };
  112. clearButton
  113. .Events ()
  114. .Clicked
  115. .InvokeCommand (ViewModel, x => x.Clear)
  116. .DisposeWith (_disposable);
  117. return clearButton;
  118. }
  119. object IViewFor.ViewModel {
  120. get => ViewModel;
  121. set => ViewModel = (LoginViewModel) value;
  122. }
  123. }
  124. }