diff --git a/samples/LoginApp.Avalonia/App.xaml.cs b/samples/LoginApp.Avalonia/App.xaml.cs index b8a86277..070e8f30 100644 --- a/samples/LoginApp.Avalonia/App.xaml.cs +++ b/samples/LoginApp.Avalonia/App.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Avalonia/Program.cs b/samples/LoginApp.Avalonia/Program.cs index 3be3568d..b927273a 100644 --- a/samples/LoginApp.Avalonia/Program.cs +++ b/samples/LoginApp.Avalonia/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Avalonia/Services/AvaloniaUserDialogs.cs b/samples/LoginApp.Avalonia/Services/AvaloniaUserDialogs.cs index 67699713..dff7b0e7 100644 --- a/samples/LoginApp.Avalonia/Services/AvaloniaUserDialogs.cs +++ b/samples/LoginApp.Avalonia/Services/AvaloniaUserDialogs.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Avalonia/Views/SignUpView.xaml.cs b/samples/LoginApp.Avalonia/Views/SignUpView.xaml.cs index eb4d08b8..18cfa2a1 100644 --- a/samples/LoginApp.Avalonia/Views/SignUpView.xaml.cs +++ b/samples/LoginApp.Avalonia/Views/SignUpView.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Uwp/App.xaml.cs b/samples/LoginApp.Uwp/App.xaml.cs index 9ff7e43c..8240e035 100644 --- a/samples/LoginApp.Uwp/App.xaml.cs +++ b/samples/LoginApp.Uwp/App.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -8,40 +8,39 @@ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -namespace LoginApp.Uwp +namespace LoginApp.Uwp; + +/// +/// Defines the main Universal Windows Application class. +/// +/// +public sealed partial class App : Application { /// - /// Defines the main Universal Windows Application class. + /// Initializes a new instance of the class. /// + public App() => InitializeComponent(); + /// - public sealed partial class App : Application + protected override void OnLaunched(LaunchActivatedEventArgs e) { - /// - /// Initializes a new instance of the class. - /// - public App() => InitializeComponent(); - - /// - protected override void OnLaunched(LaunchActivatedEventArgs e) + Frame rootFrame = Window.Current.Content as Frame; + if (rootFrame == null) { - Frame rootFrame = Window.Current.Content as Frame; - if (rootFrame == null) - { - rootFrame = new Frame(); - Window.Current.Content = rootFrame; - } - - if (e?.PrelaunchActivated == true) - { - return; - } + rootFrame = new Frame(); + Window.Current.Content = rootFrame; + } - if (rootFrame.Content == null) - { - rootFrame.Navigate(typeof(SignUpView), e?.Arguments); - } + if (e?.PrelaunchActivated == true) + { + return; + } - Window.Current.Activate(); + if (rootFrame.Content == null) + { + rootFrame.Navigate(typeof(SignUpView), e?.Arguments); } + + Window.Current.Activate(); } } diff --git a/samples/LoginApp.Uwp/LoginApp.Uwp.csproj b/samples/LoginApp.Uwp/LoginApp.Uwp.csproj index 092d40c9..b0a72a8e 100644 --- a/samples/LoginApp.Uwp/LoginApp.Uwp.csproj +++ b/samples/LoginApp.Uwp/LoginApp.Uwp.csproj @@ -18,6 +18,7 @@ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} true false + latest true diff --git a/samples/LoginApp.Uwp/Properties/AssemblyInfo.cs b/samples/LoginApp.Uwp/Properties/AssemblyInfo.cs index 81230bf1..8df4853e 100644 --- a/samples/LoginApp.Uwp/Properties/AssemblyInfo.cs +++ b/samples/LoginApp.Uwp/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Uwp/Services/UwpUserDialogs.cs b/samples/LoginApp.Uwp/Services/UwpUserDialogs.cs index 6cc88fd9..cd2875bf 100644 --- a/samples/LoginApp.Uwp/Services/UwpUserDialogs.cs +++ b/samples/LoginApp.Uwp/Services/UwpUserDialogs.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -6,14 +6,13 @@ using LoginApp.Services; using Windows.UI.Popups; -namespace LoginApp.Uwp.Services +namespace LoginApp.Uwp.Services; + +/// +/// This class defines user dialogs for the Universal Windows Platform app. +/// +public class UwpUserDialogs : IUserDialogs { - /// - /// This class defines user dialogs for the Universal Windows Platform app. - /// - public class UwpUserDialogs : IUserDialogs - { - /// - public void ShowDialog(string message) => new MessageDialog(message).ShowAsync(); - } + /// + public void ShowDialog(string message) => new MessageDialog(message).ShowAsync(); } diff --git a/samples/LoginApp.Uwp/Views/SignUpView.xaml.cs b/samples/LoginApp.Uwp/Views/SignUpView.xaml.cs index 34fee4db..c68a5c46 100644 --- a/samples/LoginApp.Uwp/Views/SignUpView.xaml.cs +++ b/samples/LoginApp.Uwp/Views/SignUpView.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -11,74 +11,73 @@ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -namespace LoginApp.Uwp.Views +namespace LoginApp.Uwp.Views; + +/// +/// A page which contains controls for signing up. +/// +public sealed partial class SignUpView : Page, IViewFor { /// - /// A page which contains controls for signing up. + /// Defines the view model dependency property for the class. /// - public sealed partial class SignUpView : Page, IViewFor - { - /// - /// Defines the view model dependency property for the class. - /// - // ReSharper disable once MemberCanBePrivate.Global due to MSDN recommendations. - public static readonly DependencyProperty ViewModelProperty = DependencyProperty - .Register(nameof(ViewModel), typeof(SignUpViewModel), typeof(SignUpView), null); + // ReSharper disable once MemberCanBePrivate.Global due to MSDN recommendations. + public static readonly DependencyProperty ViewModelProperty = DependencyProperty + .Register(nameof(ViewModel), typeof(SignUpViewModel), typeof(SignUpView), null); - /// - /// Initializes a new instance of the class. - /// - public SignUpView() + /// + /// Initializes a new instance of the class. + /// + public SignUpView() + { + ViewModel = new SignUpViewModel(null, new UwpUserDialogs()); + InitializeComponent(); + this.WhenActivated(disposables => { - ViewModel = new SignUpViewModel(null, new UwpUserDialogs()); - InitializeComponent(); - this.WhenActivated(disposables => - { - this.Bind(ViewModel, x => x.UserName, x => x.UserNameTextBox.Text) - .DisposeWith(disposables); - this.Bind(ViewModel, x => x.Password, x => x.PasswordTextBox.Text) - .DisposeWith(disposables); - this.Bind(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordTextBox.Text) - .DisposeWith(disposables); + this.Bind(ViewModel, x => x.UserName, x => x.UserNameTextBox.Text) + .DisposeWith(disposables); + this.Bind(ViewModel, x => x.Password, x => x.PasswordTextBox.Text) + .DisposeWith(disposables); + this.Bind(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordTextBox.Text) + .DisposeWith(disposables); - this.BindCommand(ViewModel, x => x.SignUp, x => x.SignUpButton) - .DisposeWith(disposables); + this.BindCommand(ViewModel, x => x.SignUp, x => x.SignUpButton) + .DisposeWith(disposables); - this.BindValidation(ViewModel, x => x.UserName, x => x.UserNameErrorLabel.Text) - .DisposeWith(disposables); - this.BindValidation(ViewModel, x => x.Password, x => x.PasswordErrorLabel.Text) - .DisposeWith(disposables); - this.BindValidation(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordErrorLabel.Text) - .DisposeWith(disposables); - this.BindValidation(ViewModel, x => x.ErrorLabel.Text) - .DisposeWith(disposables); + this.BindValidation(ViewModel, x => x.UserName, x => x.UserNameErrorLabel.Text) + .DisposeWith(disposables); + this.BindValidation(ViewModel, x => x.Password, x => x.PasswordErrorLabel.Text) + .DisposeWith(disposables); + this.BindValidation(ViewModel, x => x.ConfirmPassword, x => x.ConfirmPasswordErrorLabel.Text) + .DisposeWith(disposables); + this.BindValidation(ViewModel, x => x.ErrorLabel.Text) + .DisposeWith(disposables); - this.WhenAnyValue(x => x.UserNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text)) - .BindTo(this, x => x.UserNameErrorLabel.Visibility) - .DisposeWith(disposables); - this.WhenAnyValue(x => x.PasswordErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text)) - .BindTo(this, x => x.PasswordErrorLabel.Visibility) - .DisposeWith(disposables); - this.WhenAnyValue(x => x.ConfirmPasswordErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text)) - .BindTo(this, x => x.ConfirmPasswordErrorLabel.Visibility) - .DisposeWith(disposables); - }); - } + this.WhenAnyValue(x => x.UserNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text)) + .BindTo(this, x => x.UserNameErrorLabel.Visibility) + .DisposeWith(disposables); + this.WhenAnyValue(x => x.PasswordErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text)) + .BindTo(this, x => x.PasswordErrorLabel.Visibility) + .DisposeWith(disposables); + this.WhenAnyValue(x => x.ConfirmPasswordErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text)) + .BindTo(this, x => x.ConfirmPasswordErrorLabel.Visibility) + .DisposeWith(disposables); + }); + } - /// - /// Gets or sets the view model. - /// - public SignUpViewModel ViewModel - { - get => (SignUpViewModel)GetValue(ViewModelProperty); - set => SetValue(ViewModelProperty, value); - } + /// + /// Gets or sets the view model. + /// + public SignUpViewModel ViewModel + { + get => (SignUpViewModel)GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } - /// - object IViewFor.ViewModel - { - get => ViewModel; - set => ViewModel = (SignUpViewModel)value; - } + /// + object IViewFor.ViewModel + { + get => ViewModel; + set => ViewModel = (SignUpViewModel)value; } } diff --git a/samples/LoginApp.WinForms/Program.cs b/samples/LoginApp.WinForms/Program.cs index dc4a2367..9b9b160f 100644 --- a/samples/LoginApp.WinForms/Program.cs +++ b/samples/LoginApp.WinForms/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.WinForms/Services/WindowsUserDialogs.cs b/samples/LoginApp.WinForms/Services/WindowsUserDialogs.cs index e8549fc1..6cc74ba9 100644 --- a/samples/LoginApp.WinForms/Services/WindowsUserDialogs.cs +++ b/samples/LoginApp.WinForms/Services/WindowsUserDialogs.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.WinForms/Views/SignUpView.cs b/samples/LoginApp.WinForms/Views/SignUpView.cs index 79df8715..c063c57c 100644 --- a/samples/LoginApp.WinForms/Views/SignUpView.cs +++ b/samples/LoginApp.WinForms/Views/SignUpView.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Wpf/App.xaml.cs b/samples/LoginApp.Wpf/App.xaml.cs index f7a9f079..b6b0d91f 100644 --- a/samples/LoginApp.Wpf/App.xaml.cs +++ b/samples/LoginApp.Wpf/App.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Wpf/AppBootstrapper.cs b/samples/LoginApp.Wpf/AppBootstrapper.cs index 01227281..9713e897 100644 --- a/samples/LoginApp.Wpf/AppBootstrapper.cs +++ b/samples/LoginApp.Wpf/AppBootstrapper.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Wpf/Program.cs b/samples/LoginApp.Wpf/Program.cs index 540474c6..d1af83f9 100644 --- a/samples/LoginApp.Wpf/Program.cs +++ b/samples/LoginApp.Wpf/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Wpf/Services/WindowsUserDialogs.cs b/samples/LoginApp.Wpf/Services/WindowsUserDialogs.cs index a2981977..c47bea07 100644 --- a/samples/LoginApp.Wpf/Services/WindowsUserDialogs.cs +++ b/samples/LoginApp.Wpf/Services/WindowsUserDialogs.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp.Wpf/Views/SignUpView.xaml.cs b/samples/LoginApp.Wpf/Views/SignUpView.xaml.cs index efd7ef39..45d5ffbc 100644 --- a/samples/LoginApp.Wpf/Views/SignUpView.xaml.cs +++ b/samples/LoginApp.Wpf/Views/SignUpView.xaml.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/samples/LoginApp/LoginApp.csproj b/samples/LoginApp/LoginApp.csproj index 87950892..e9d4e84e 100644 --- a/samples/LoginApp/LoginApp.csproj +++ b/samples/LoginApp/LoginApp.csproj @@ -1,6 +1,7 @@  netstandard2.0 + latest diff --git a/samples/LoginApp/Services/IUserDialogs.cs b/samples/LoginApp/Services/IUserDialogs.cs index 8e0d0bc3..2ebc794c 100644 --- a/samples/LoginApp/Services/IUserDialogs.cs +++ b/samples/LoginApp/Services/IUserDialogs.cs @@ -1,19 +1,18 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. -namespace LoginApp.Services +namespace LoginApp.Services; + +/// +/// This interface defines a platform-specific notification manager. +/// +public interface IUserDialogs { /// - /// This interface defines a platform-specific notification manager. + /// Displays a platform-specific notification containing a message. /// - public interface IUserDialogs - { - /// - /// Displays a platform-specific notification containing a message. - /// - /// The message to show. - void ShowDialog(string message); - } + /// The message to show. + void ShowDialog(string message); } diff --git a/samples/LoginApp/ViewModels/SignUpViewModel.cs b/samples/LoginApp/ViewModels/SignUpViewModel.cs index f16185cf..39232c6f 100644 --- a/samples/LoginApp/ViewModels/SignUpViewModel.cs +++ b/samples/LoginApp/ViewModels/SignUpViewModel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -16,141 +16,140 @@ using ReactiveUI.Validation.States; using Splat; -namespace LoginApp.ViewModels +namespace LoginApp.ViewModels; + +/// +/// A view model which shows controls to create an account. +/// +public class SignUpViewModel : ReactiveValidationObject, IRoutableViewModel, IActivatableViewModel { + private readonly ObservableAsPropertyHelper _isBusy; + private readonly IUserDialogs _dialogs; + + /// + /// Initializes a new instance of the class. + /// + /// The screen used for routing purposes. + /// implementation to show dialogs. + public SignUpViewModel(IScreen hostScreen = null, IUserDialogs dialogs = null) + { + _dialogs = dialogs ?? Locator.Current.GetService(); + HostScreen = hostScreen ?? Locator.Current.GetService(); + SignUp = ReactiveCommand.Create(SignUpImpl, this.IsValid()); + + // These are the basic property validation rules that accept a property selector, + // listen to the changes of that property, and execute the validation function + // when the selected property changes. + this.ValidationRule( + vm => vm.UserName, + name => !string.IsNullOrWhiteSpace(name), + "UserName is required."); + + this.ValidationRule( + vm => vm.Password, + password => !string.IsNullOrWhiteSpace(password), + "Password is required."); + + this.ValidationRule( + vm => vm.Password, + password => password?.Length > 2, + password => $"Password should be longer, current length: {password.Length}"); + + this.ValidationRule( + vm => vm.ConfirmPassword, + confirmation => !string.IsNullOrWhiteSpace(confirmation), + "Confirm password field is required."); + + // Here we construct an IObservable that defines a complex validation rule + // based on multiple properties. We associate this IObservable with the + // 'ConfirmPassword' property via a call to the ValidationRule extension method. + IObservable passwordsObservable = + this.WhenAnyValue( + x => x.Password, + x => x.ConfirmPassword, + (password, confirmation) => + password == confirmation); + + this.ValidationRule( + vm => vm.ConfirmPassword, + passwordsObservable, + "Passwords must match."); + + // Here we pass a complex IObservable to the ValidationRule. That observable + // emits an empty string when UserName is valid, and emits a non-empty when UserName + // is either invalid, or just changed and hasn't been validated yet. + IObservable usernameValidated = + this.WhenAnyValue(x => x.UserName) + .Throttle(TimeSpan.FromSeconds(0.7), RxApp.TaskpoolScheduler) + .SelectMany(ValidateNameImpl) + .ObserveOn(RxApp.MainThreadScheduler); + + IObservable usernameDirty = + this.WhenAnyValue(x => x.UserName) + .Select(name => new ValidationState(false, "Please wait...")); + + this.ValidationRule( + vm => vm.UserName, + usernameValidated.Merge(usernameDirty)); + + _isBusy = usernameValidated + .Select(message => false) + .Merge(usernameDirty.Select(message => true)) + .ToProperty(this, x => x.IsBusy); + } + + /// + /// Gets or sets the typed . + /// + [Reactive] + public string UserName { get; set; } = string.Empty; + + /// + /// Gets or sets the typed . + /// + [Reactive] + public string Password { get; set; } = string.Empty; + + /// + /// Gets or sets the typed . + /// + [Reactive] + public string ConfirmPassword { get; set; } = string.Empty; + + /// + /// Gets a value indicating whether the form is currently validating asynchronously. + /// + public bool IsBusy => _isBusy.Value; + /// - /// A view model which shows controls to create an account. + /// Gets a command which will create the account. /// - public class SignUpViewModel : ReactiveValidationObject, IRoutableViewModel, IActivatableViewModel + public ReactiveCommand SignUp { get; } + + /// + /// Gets the current page path. + /// + public string UrlPathSegment { get; } = "Sign Up"; + + /// + /// Gets the screen used for routing operations. + /// + public IScreen HostScreen { get; } + + /// + /// Gets the activator which contains context information for use in activation of the view model. + /// + public ViewModelActivator Activator { get; } = new ViewModelActivator(); + + private static async Task ValidateNameImpl(string username) { - private readonly ObservableAsPropertyHelper _isBusy; - private readonly IUserDialogs _dialogs; - - /// - /// Initializes a new instance of the class. - /// - /// The screen used for routing purposes. - /// implementation to show dialogs. - public SignUpViewModel(IScreen hostScreen = null, IUserDialogs dialogs = null) - { - _dialogs = dialogs ?? Locator.Current.GetService(); - HostScreen = hostScreen ?? Locator.Current.GetService(); - SignUp = ReactiveCommand.Create(SignUpImpl, this.IsValid()); - - // These are the basic property validation rules that accept a property selector, - // listen to the changes of that property, and execute the validation function - // when the selected property changes. - this.ValidationRule( - vm => vm.UserName, - name => !string.IsNullOrWhiteSpace(name), - "UserName is required."); - - this.ValidationRule( - vm => vm.Password, - password => !string.IsNullOrWhiteSpace(password), - "Password is required."); - - this.ValidationRule( - vm => vm.Password, - password => password?.Length > 2, - password => $"Password should be longer, current length: {password.Length}"); - - this.ValidationRule( - vm => vm.ConfirmPassword, - confirmation => !string.IsNullOrWhiteSpace(confirmation), - "Confirm password field is required."); - - // Here we construct an IObservable that defines a complex validation rule - // based on multiple properties. We associate this IObservable with the - // 'ConfirmPassword' property via a call to the ValidationRule extension method. - IObservable passwordsObservable = - this.WhenAnyValue( - x => x.Password, - x => x.ConfirmPassword, - (password, confirmation) => - password == confirmation); - - this.ValidationRule( - vm => vm.ConfirmPassword, - passwordsObservable, - "Passwords must match."); - - // Here we pass a complex IObservable to the ValidationRule. That observable - // emits an empty string when UserName is valid, and emits a non-empty when UserName - // is either invalid, or just changed and hasn't been validated yet. - IObservable usernameValidated = - this.WhenAnyValue(x => x.UserName) - .Throttle(TimeSpan.FromSeconds(0.7), RxApp.TaskpoolScheduler) - .SelectMany(ValidateNameImpl) - .ObserveOn(RxApp.MainThreadScheduler); - - IObservable usernameDirty = - this.WhenAnyValue(x => x.UserName) - .Select(name => new ValidationState(false, "Please wait...")); - - this.ValidationRule( - vm => vm.UserName, - usernameValidated.Merge(usernameDirty)); - - _isBusy = usernameValidated - .Select(message => false) - .Merge(usernameDirty.Select(message => true)) - .ToProperty(this, x => x.IsBusy); - } - - /// - /// Gets or sets the typed . - /// - [Reactive] - public string UserName { get; set; } = string.Empty; - - /// - /// Gets or sets the typed . - /// - [Reactive] - public string Password { get; set; } = string.Empty; - - /// - /// Gets or sets the typed . - /// - [Reactive] - public string ConfirmPassword { get; set; } = string.Empty; - - /// - /// Gets a value indicating whether the form is currently validating asynchronously. - /// - public bool IsBusy => _isBusy.Value; - - /// - /// Gets a command which will create the account. - /// - public ReactiveCommand SignUp { get; } - - /// - /// Gets the current page path. - /// - public string UrlPathSegment { get; } = "Sign Up"; - - /// - /// Gets the screen used for routing operations. - /// - public IScreen HostScreen { get; } - - /// - /// Gets the activator which contains context information for use in activation of the view model. - /// - public ViewModelActivator Activator { get; } = new ViewModelActivator(); - - private static async Task ValidateNameImpl(string username) - { - await Task.Delay(TimeSpan.FromSeconds(0.5)).ConfigureAwait(false); - return username.Length < 2 - ? new ValidationState(false, "The name is too short.") - : username.Any(letter => !char.IsLetter(letter)) - ? new ValidationState(false, "Only letters allowed.") - : ValidationState.Valid; - } - - private void SignUpImpl() => _dialogs.ShowDialog("User created successfully."); + await Task.Delay(TimeSpan.FromSeconds(0.5)).ConfigureAwait(false); + return username.Length < 2 + ? new ValidationState(false, "The name is too short.") + : username.Any(letter => !char.IsLetter(letter)) + ? new ValidationState(false, "Only letters allowed.") + : ValidationState.Valid; } + + private void SignUpImpl() => _dialogs.ShowDialog("User created successfully."); } diff --git a/src/ReactiveUI.Validation.AndroidSupport/Extensions/ViewForExtensions.cs b/src/ReactiveUI.Validation.AndroidSupport/Extensions/ViewForExtensions.cs index f83844b1..adb33710 100644 --- a/src/ReactiveUI.Validation.AndroidSupport/Extensions/ViewForExtensions.cs +++ b/src/ReactiveUI.Validation.AndroidSupport/Extensions/ViewForExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -178,4 +178,4 @@ public static class ViewForExtensions (_, errorText) => viewProperty.Error = errorText, formatter); } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Validation.AndroidX/Extensions/ViewForExtensions.cs b/src/ReactiveUI.Validation.AndroidX/Extensions/ViewForExtensions.cs index cf45db32..a899fca7 100644 --- a/src/ReactiveUI.Validation.AndroidX/Extensions/ViewForExtensions.cs +++ b/src/ReactiveUI.Validation.AndroidX/Extensions/ViewForExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Abstractions/IValidatableViewModel.cs b/src/ReactiveUI.Validation/Abstractions/IValidatableViewModel.cs index a3c06434..217e1582 100755 --- a/src/ReactiveUI.Validation/Abstractions/IValidatableViewModel.cs +++ b/src/ReactiveUI.Validation/Abstractions/IValidatableViewModel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Collections/ValidationText.cs b/src/ReactiveUI.Validation/Collections/ValidationText.cs index a322a514..af4b7802 100755 --- a/src/ReactiveUI.Validation/Collections/ValidationText.cs +++ b/src/ReactiveUI.Validation/Collections/ValidationText.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Comparators/ValidationStateComparer.cs b/src/ReactiveUI.Validation/Comparators/ValidationStateComparer.cs index f0d8d212..282b374f 100755 --- a/src/ReactiveUI.Validation/Comparators/ValidationStateComparer.cs +++ b/src/ReactiveUI.Validation/Comparators/ValidationStateComparer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Components/Abstractions/IPropertyValidationComponent.cs b/src/ReactiveUI.Validation/Components/Abstractions/IPropertyValidationComponent.cs index 086d63be..d67d092a 100644 --- a/src/ReactiveUI.Validation/Components/Abstractions/IPropertyValidationComponent.cs +++ b/src/ReactiveUI.Validation/Components/Abstractions/IPropertyValidationComponent.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Components/Abstractions/IValidatesProperties.cs b/src/ReactiveUI.Validation/Components/Abstractions/IValidatesProperties.cs index 3382a9d7..54923bc5 100644 --- a/src/ReactiveUI.Validation/Components/Abstractions/IValidatesProperties.cs +++ b/src/ReactiveUI.Validation/Components/Abstractions/IValidatesProperties.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Components/Abstractions/IValidationComponent.cs b/src/ReactiveUI.Validation/Components/Abstractions/IValidationComponent.cs index 2ea6df0b..a15912f1 100755 --- a/src/ReactiveUI.Validation/Components/Abstractions/IValidationComponent.cs +++ b/src/ReactiveUI.Validation/Components/Abstractions/IValidationComponent.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Components/BasePropertyValidation.cs b/src/ReactiveUI.Validation/Components/BasePropertyValidation.cs index 98af8373..16917f5e 100755 --- a/src/ReactiveUI.Validation/Components/BasePropertyValidation.cs +++ b/src/ReactiveUI.Validation/Components/BasePropertyValidation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Components/ObservableValidation.cs b/src/ReactiveUI.Validation/Components/ObservableValidation.cs index 8fe5c3bd..7b214461 100644 --- a/src/ReactiveUI.Validation/Components/ObservableValidation.cs +++ b/src/ReactiveUI.Validation/Components/ObservableValidation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Contexts/ValidationContext.cs b/src/ReactiveUI.Validation/Contexts/ValidationContext.cs index 8c651e7d..248fe7c6 100755 --- a/src/ReactiveUI.Validation/Contexts/ValidationContext.cs +++ b/src/ReactiveUI.Validation/Contexts/ValidationContext.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Extensions/ExpressionExtensions.cs b/src/ReactiveUI.Validation/Extensions/ExpressionExtensions.cs index bd49f653..31c859ad 100644 --- a/src/ReactiveUI.Validation/Extensions/ExpressionExtensions.cs +++ b/src/ReactiveUI.Validation/Extensions/ExpressionExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Extensions/ValidatableViewModelExtensions.cs b/src/ReactiveUI.Validation/Extensions/ValidatableViewModelExtensions.cs index da8f5551..e9506cfc 100644 --- a/src/ReactiveUI.Validation/Extensions/ValidatableViewModelExtensions.cs +++ b/src/ReactiveUI.Validation/Extensions/ValidatableViewModelExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Extensions/ValidatesPropertiesExtensions.cs b/src/ReactiveUI.Validation/Extensions/ValidatesPropertiesExtensions.cs index 5807f6df..5a100d04 100644 --- a/src/ReactiveUI.Validation/Extensions/ValidatesPropertiesExtensions.cs +++ b/src/ReactiveUI.Validation/Extensions/ValidatesPropertiesExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Extensions/ValidationContextExtensions.cs b/src/ReactiveUI.Validation/Extensions/ValidationContextExtensions.cs index 493a2448..1eeff169 100755 --- a/src/ReactiveUI.Validation/Extensions/ValidationContextExtensions.cs +++ b/src/ReactiveUI.Validation/Extensions/ValidationContextExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Extensions/ViewForExtensions.cs b/src/ReactiveUI.Validation/Extensions/ViewForExtensions.cs index 65c2690e..38d739a3 100755 --- a/src/ReactiveUI.Validation/Extensions/ViewForExtensions.cs +++ b/src/ReactiveUI.Validation/Extensions/ViewForExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Formatters/Abstractions/IValidationTextFormatter.cs b/src/ReactiveUI.Validation/Formatters/Abstractions/IValidationTextFormatter.cs index 6b5c8003..b753b40b 100755 --- a/src/ReactiveUI.Validation/Formatters/Abstractions/IValidationTextFormatter.cs +++ b/src/ReactiveUI.Validation/Formatters/Abstractions/IValidationTextFormatter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Formatters/SingleLineFormatter.cs b/src/ReactiveUI.Validation/Formatters/SingleLineFormatter.cs index 6724c2ba..c8b36ea8 100755 --- a/src/ReactiveUI.Validation/Formatters/SingleLineFormatter.cs +++ b/src/ReactiveUI.Validation/Formatters/SingleLineFormatter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Helpers/ReactiveValidationObject.cs b/src/ReactiveUI.Validation/Helpers/ReactiveValidationObject.cs index 784de1b5..4342ea4e 100644 --- a/src/ReactiveUI.Validation/Helpers/ReactiveValidationObject.cs +++ b/src/ReactiveUI.Validation/Helpers/ReactiveValidationObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/Helpers/ValidationHelper.cs b/src/ReactiveUI.Validation/Helpers/ValidationHelper.cs index ac2ff4c4..5ab7ab9e 100755 --- a/src/ReactiveUI.Validation/Helpers/ValidationHelper.cs +++ b/src/ReactiveUI.Validation/Helpers/ValidationHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/States/IValidationState.cs b/src/ReactiveUI.Validation/States/IValidationState.cs index 8b105a47..7a3480c9 100644 --- a/src/ReactiveUI.Validation/States/IValidationState.cs +++ b/src/ReactiveUI.Validation/States/IValidationState.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/States/ValidationState.cs b/src/ReactiveUI.Validation/States/ValidationState.cs index e65d517d..60d0207d 100755 --- a/src/ReactiveUI.Validation/States/ValidationState.cs +++ b/src/ReactiveUI.Validation/States/ValidationState.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/ValidationBindings/Abstractions/IValidationBinding.cs b/src/ReactiveUI.Validation/ValidationBindings/Abstractions/IValidationBinding.cs index 64452bca..8dc66fa7 100755 --- a/src/ReactiveUI.Validation/ValidationBindings/Abstractions/IValidationBinding.cs +++ b/src/ReactiveUI.Validation/ValidationBindings/Abstractions/IValidationBinding.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/ReactiveUI.Validation/ValidationBindings/ValidationBinding.cs b/src/ReactiveUI.Validation/ValidationBindings/ValidationBinding.cs index b0c9e288..439ed783 100755 --- a/src/ReactiveUI.Validation/ValidationBindings/ValidationBinding.cs +++ b/src/ReactiveUI.Validation/ValidationBindings/ValidationBinding.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. diff --git a/src/stylecop.json b/src/stylecop.json index ba9d2381..44a6ef8d 100644 --- a/src/stylecop.json +++ b/src/stylecop.json @@ -13,7 +13,7 @@ "documentPrivateFields": false, "documentationCulture": "en-US", "companyName": ".NET Foundation and Contributors", - "copyrightText": "Copyright (c) 2021 {companyName}. All rights reserved.\nLicensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the {licenseName} license.\nSee the {licenseFile} file in the project root for full license information.", + "copyrightText": "Copyright (c) 2022 {companyName}. All rights reserved.\nLicensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the {licenseName} license.\nSee the {licenseFile} file in the project root for full license information.", "variables": { "licenseName": "MIT", "licenseFile": "LICENSE"