LoginView.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 (LoginProgressLabel ());
  19. }
  20. public LoginViewModel ViewModel { get; set; }
  21. protected override void Dispose (bool disposing) {
  22. _disposable.Dispose ();
  23. base.Dispose (disposing);
  24. }
  25. TextField UsernameInput () {
  26. var usernameInput = new TextField (ViewModel.Username) { Width = 40 };
  27. ViewModel
  28. .WhenAnyValue (x => x.Username)
  29. .BindTo (usernameInput, x => x.Text)
  30. .DisposeWith (_disposable);
  31. usernameInput
  32. .Events ()
  33. .TextChanged
  34. .Select (old => usernameInput.Text.ToString ())
  35. .DistinctUntilChanged ()
  36. .BindTo (ViewModel, x => x.Username)
  37. .DisposeWith (_disposable);
  38. return usernameInput;
  39. }
  40. Label UsernameLengthLabel () {
  41. var usernameLengthLabel = new Label { Width = 40 };
  42. ViewModel
  43. .WhenAnyValue (x => x.UsernameLength)
  44. .Select (length => ustring.Make ($"Username ({length} characters)"))
  45. .BindTo (usernameLengthLabel, x => x.Text)
  46. .DisposeWith (_disposable);
  47. return usernameLengthLabel;
  48. }
  49. TextField PasswordInput () {
  50. var passwordInput = new TextField (ViewModel.Password) { Width = 40 };
  51. ViewModel
  52. .WhenAnyValue (x => x.Password)
  53. .BindTo (passwordInput, x => x.Text)
  54. .DisposeWith (_disposable);
  55. passwordInput
  56. .Events ()
  57. .TextChanged
  58. .Select (old => passwordInput.Text.ToString ())
  59. .DistinctUntilChanged ()
  60. .BindTo (ViewModel, x => x.Password)
  61. .DisposeWith (_disposable);
  62. return passwordInput;
  63. }
  64. Label PasswordLengthLabel () {
  65. var passwordLengthLabel = new Label { Width = 40 };
  66. ViewModel
  67. .WhenAnyValue (x => x.PasswordLength)
  68. .Select (length => ustring.Make ($"Password ({length} characters)"))
  69. .BindTo (passwordLengthLabel, x => x.Text)
  70. .DisposeWith (_disposable);
  71. return passwordLengthLabel;
  72. }
  73. Label ValidationLabel () {
  74. var error = ustring.Make("Please, enter user name and password.");
  75. var success = ustring.Make("The input is valid!");
  76. var validationLabel = new Label(error) { Width = 40 };
  77. ViewModel
  78. .WhenAnyValue (x => x.IsValid)
  79. .Select (valid => valid ? success : error)
  80. .BindTo (validationLabel, x => x.Text)
  81. .DisposeWith (_disposable);
  82. ViewModel
  83. .WhenAnyValue (x => x.IsValid)
  84. .Select (valid => valid ? Colors.Base : Colors.Error)
  85. .BindTo (validationLabel, x => x.ColorScheme)
  86. .DisposeWith (_disposable);
  87. return validationLabel;
  88. }
  89. Label LoginProgressLabel () {
  90. var progress = ustring.Make ("Logging in...");
  91. var idle = ustring.Make ("Press 'Login' to log in.");
  92. var loginProgressLabel = new Label(idle) { Width = 40 };
  93. ViewModel
  94. .WhenAnyObservable (x => x.Login.IsExecuting)
  95. .Select (executing => executing ? progress : idle)
  96. .BindTo (loginProgressLabel, x => x.Text)
  97. .DisposeWith (_disposable);
  98. return loginProgressLabel;
  99. }
  100. Button LoginButton () {
  101. var loginButton = new Button ("Login") { Width = 40 };
  102. loginButton
  103. .Events ()
  104. .Clicked
  105. .InvokeCommand (ViewModel, x => x.Login)
  106. .DisposeWith (_disposable);
  107. return loginButton;
  108. }
  109. object IViewFor.ViewModel {
  110. get => ViewModel;
  111. set => ViewModel = (LoginViewModel) value;
  112. }
  113. }
  114. }