feat: Advanced Use of ReactiveUI.Validation (#44)
* Update packages, add validation messages to UWP * Don't use the obsolete ReactiveUI.Validation APIs * Update README.md * Add validations for Xamarin.Forms
This commit is contained in:
Родитель
74b0ea6691
Коммит
0a037dfc38
|
@ -47,9 +47,11 @@ To compile the <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/"
|
|||
### Technologies and Tools Used
|
||||
|
||||
- <a href="https://reactiveui.net/">ReactiveUI</a> modern MVVM framework
|
||||
- <a href="https://github.com/reactiveui/reactiveui.validation">ReactiveUI.Validation</a> reactive validation library
|
||||
- <a href="https://reactiveui.net/docs/handbook/events/">ReactiveUI.Events</a> turning regular events into observables
|
||||
- <a href="https://github.com/reactiveui/DynamicData">DynamicData</a> reactive collections
|
||||
- <a href="http://github.com/avaloniaui">AvaloniaUI</a> cross-platform XAML-based GUI framework
|
||||
- <a href="http://github.com/worldbeater/citrus.avalonia">Citrus</a> bright and modern AvaloniaUI theme
|
||||
- <a href="http://github.com/worldbeater/citrus.avalonia">Citrus.Avalonia</a> bright and modern AvaloniaUI theme
|
||||
- <a href="https://github.com/reactiveui/Akavache">Akavache</a> persistent key-value store
|
||||
- <a href="https://github.com/nuke-build/nuke">Nuke</a> build automation system for C#/.NET
|
||||
- <a href="https://github.com/xunit/xunit">XUnit</a> unit testing tool for .NET
|
||||
|
@ -66,7 +68,6 @@ To compile the <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/"
|
|||
- <a href="https://github.com/googleapis/google-api-dotnet-client">Google Drive</a> client SDK for .NET
|
||||
- <a href="https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit">Material Design</a> XAML controls and styles
|
||||
- <a href="https://github.com/MahApps/MahApps.Metro">MahApps Metro</a> XAML controls and styled windows
|
||||
- <a href="https://reactiveui.net/docs/handbook/events/">ReactiveUI.Events</a> turning regular events into observables
|
||||
- <a href="https://github.com/Fody/Costura">Costura.Fody</a> which embeds references as resources
|
||||
- <a href="https://www.jetbrains.com/rider/">JetBrains Rider</a> and <a href="https://visualstudio.microsoft.com/">Microsoft Visual Studio</a> IDEs
|
||||
- <a href="https://github.com/fornever/avaloniarider">AvaloniaRider</a> plugin for visual designer support
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
<TextBlock Text="Please, enter new folder name:" Margin="0 5" />
|
||||
<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PlaceholderText="Please, enter the new name of the folder..." />
|
||||
<TextBlock x:Name="FolderNameErrorLabel"
|
||||
Text="Folder name error label"
|
||||
Foreground="Red" />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3*" />
|
||||
|
@ -56,5 +59,8 @@
|
|||
HorizontalAlignment="Stretch"
|
||||
Margin="0 10" />
|
||||
</Grid>
|
||||
<TextBlock x:Name="FormErrorLabel"
|
||||
Text="Form error label"
|
||||
Foreground="Red" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
|
@ -13,7 +17,20 @@ namespace Camelotia.Presentation.Uwp.Views
|
|||
public CreateFolderView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindValidation(ViewModel, x => x.Name, x => x.FolderNameErrorLabel.Text)
|
||||
.DisposeWith(disposables);
|
||||
this.BindValidation(ViewModel, x => x.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(x => x.FolderNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FolderNameErrorLabel.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
public ICreateFolderViewModel ViewModel
|
||||
|
|
|
@ -34,13 +34,22 @@
|
|||
<TextBlock Text="Please, enter your user name:" Margin="0 5" />
|
||||
<TextBox Text="{x:Bind ViewModel.Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PlaceholderText="Please, enter the user name..." />
|
||||
<TextBlock x:Name="UserNameErrorLabel"
|
||||
Text="User name error label"
|
||||
Foreground="Red" />
|
||||
<TextBlock Text="Please, enter your password:" Margin="0 5" />
|
||||
<PasswordBox Password="{x:Bind ViewModel.Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PlaceholderText="Please, enter the password..." />
|
||||
<TextBlock x:Name="PasswordErrorLabel"
|
||||
Text="Password error label"
|
||||
Foreground="Red" />
|
||||
<Button Content="Login"
|
||||
HorizontalAlignment="Stretch"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
Command="{x:Bind ViewModel.Login, Mode=OneWay}"
|
||||
Margin="0 10" />
|
||||
<TextBlock x:Name="FormErrorLabel"
|
||||
Text="Form error label"
|
||||
Foreground="Red" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
|
@ -13,7 +17,25 @@ namespace Camelotia.Presentation.Uwp.Views
|
|||
public DirectAuthView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(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.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.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.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
public IDirectAuthViewModel ViewModel
|
||||
|
|
|
@ -43,16 +43,31 @@
|
|||
Text="{x:Bind ViewModel.Port, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PlaceholderText="The port..." />
|
||||
</Grid>
|
||||
<TextBlock x:Name="HostNameErrorLabel"
|
||||
Text="Host name error label"
|
||||
Foreground="Red" />
|
||||
<TextBlock x:Name="PortErrorLabel"
|
||||
Text="Port error label"
|
||||
Foreground="Red" />
|
||||
<TextBlock Text="Please, enter your user name:" Margin="0 5" />
|
||||
<TextBox Text="{x:Bind ViewModel.Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PlaceholderText="Please, enter the user name..." />
|
||||
<TextBlock x:Name="UserNameErrorLabel"
|
||||
Text="User name error label"
|
||||
Foreground="Red" />
|
||||
<TextBlock Text="Please, enter your password:" Margin="0 5" />
|
||||
<PasswordBox Password="{x:Bind ViewModel.Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PlaceholderText="Please, enter the password..." />
|
||||
<TextBlock x:Name="PasswordErrorLabel"
|
||||
Text="Password error label"
|
||||
Foreground="Red" />
|
||||
<Button Content="Login"
|
||||
HorizontalAlignment="Stretch"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
Command="{x:Bind ViewModel.Login, Mode=OneWay}"
|
||||
Margin="0 10" />
|
||||
<TextBlock x:Name="FormErrorLabel"
|
||||
Text="Form error label"
|
||||
Foreground="Red" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
|
@ -13,7 +17,35 @@ namespace Camelotia.Presentation.Uwp.Views
|
|||
public HostAuthView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindValidation(ViewModel, x => x.Address, x => x.HostNameErrorLabel.Text)
|
||||
.DisposeWith(disposables);
|
||||
this.BindValidation(ViewModel, x => x.Port, x => x.PortErrorLabel.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.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(x => x.HostNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.HostNameErrorLabel.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.PortErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.PortErrorLabel.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.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
public IHostAuthViewModel ViewModel
|
||||
|
|
|
@ -37,7 +37,10 @@
|
|||
</StackPanel>
|
||||
<TextBlock Text="Please, enter new file name:" Margin="0 5" />
|
||||
<TextBox Text="{x:Bind ViewModel.NewName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PlaceholderText="Please, enter the new name of the file..." />
|
||||
PlaceholderText="Please, enter the new name of the file..." />
|
||||
<TextBlock x:Name="FileNameErrorLabel"
|
||||
Text="File name error label"
|
||||
Foreground="Red" />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3*" />
|
||||
|
@ -56,5 +59,8 @@
|
|||
HorizontalAlignment="Stretch"
|
||||
Margin="0 10" />
|
||||
</Grid>
|
||||
<TextBlock x:Name="FormErrorLabel"
|
||||
Text="Form error label"
|
||||
Foreground="Red" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
|
@ -13,7 +17,20 @@ namespace Camelotia.Presentation.Uwp.Views
|
|||
public RenameFileView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindValidation(ViewModel, x => x.NewName, x => x.FileNameErrorLabel.Text)
|
||||
.DisposeWith(disposables);
|
||||
this.BindValidation(ViewModel, x => x.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(x => x.FileNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FileNameErrorLabel.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
public IRenameFileViewModel ViewModel
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
<UseWpf>true</UseWpf>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="akavache" Version="6.10.20" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.2.0" />
|
||||
<PackageReference Include="akavache" Version="7.1.1" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.3.0" />
|
||||
<PackageReference Include="MaterialDesignColors" Version="1.2.7" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="3.2.0" />
|
||||
<PackageReference Include="MaterialDesignThemes.MahApps" Version="0.1.5" />
|
||||
<PackageReference Include="ReactiveUI.Events.WPF" Version="11.5.35" />
|
||||
<PackageReference Include="ReactiveUI.WPF" Version="11.5.35" />
|
||||
<PackageReference Include="ReactiveUI.Events.WPF" Version="12.1.1" />
|
||||
<PackageReference Include="ReactiveUI.WPF" Version="12.1.1" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.0.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -58,8 +58,8 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="System.Reactive" Version="4.4.1" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
|
||||
<PackageReference Include="ReactiveUI.AndroidSupport" Version="11.5.35" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.7.0.1351" />
|
||||
<PackageReference Include="ReactiveUI.AndroidSupport" Version="12.1.1" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.8.0.1560" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.Preference" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Media.Compat" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Fragment" Version="28.0.0.3" />
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Camelotia.Presentation.Xamarin.App">
|
||||
<Application.Resources>
|
||||
|
||||
<ResourceDictionary>
|
||||
<Style x:Key="ErrorLabelStyle" TargetType="Label">
|
||||
<Setter Property="TextColor" Value="Red" />
|
||||
<Setter Property="Margin" Value="3, -5, 3, 0" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -10,9 +10,9 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI.XamForms" Version="11.5.35" />
|
||||
<PackageReference Include="ReactiveUI.Events.XamForms" Version="11.5.35" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.7.0.1351" />
|
||||
<PackageReference Include="ReactiveUI.XamForms" Version="12.1.1" />
|
||||
<PackageReference Include="ReactiveUI.Events.XamForms" Version="12.1.1" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.8.0.1560" />
|
||||
<PackageReference Include="Xam.Plugin.Iconize" Version="3.5.0.112" />
|
||||
<PackageReference Include="Xam.Plugin.Iconize.FontAwesome" Version="3.5.0.112" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
Title="Authentication Required"
|
||||
mc:Ignorable="d">
|
||||
<d:ContentPage.BindingContext>
|
||||
<!-- ReSharper disable once Xaml.InvalidType -->
|
||||
<designTime:DesignTimeAuthViewModel />
|
||||
</d:ContentPage.BindingContext>
|
||||
</rxui:ReactiveTabbedPage>
|
|
@ -26,6 +26,9 @@
|
|||
TextColor="Red"
|
||||
Margin="0, 15" />
|
||||
<Entry Text="{Binding Name}" Placeholder="New folder name"/>
|
||||
<Label x:Name="FolderNameErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3*" />
|
||||
|
@ -40,6 +43,9 @@
|
|||
Margin="0, 10"
|
||||
Text="Close" />
|
||||
</Grid>
|
||||
<Label x:Name="FormErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage.Content>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
using ReactiveUI.XamForms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
|
@ -11,7 +15,20 @@ namespace Camelotia.Presentation.Xamarin.Views
|
|||
public CreateFolderView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindValidation(ViewModel, x => x.Name, x => x.FolderNameErrorLabel.Text)
|
||||
.DisposeWith(disposables);
|
||||
this.BindValidation(ViewModel, x => x.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(x => x.FolderNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FolderNameErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,8 +26,17 @@
|
|||
TextColor="Red"
|
||||
Margin="0, 15" />
|
||||
<Entry Text="{Binding Username}" Placeholder="Please, enter your login" />
|
||||
<Label x:Name="UserNameErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<Entry Text="{Binding Password}" IsPassword="True" Placeholder="Please, enter your password" />
|
||||
<Label x:Name="PasswordErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<controls:AccentButton Text="Login" Command="{Binding Login}" />
|
||||
<Label x:Name="FormErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage.Content>
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using ReactiveUI.XamForms;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
|
||||
namespace Camelotia.Presentation.Xamarin.Views
|
||||
{
|
||||
|
@ -11,7 +15,25 @@ namespace Camelotia.Presentation.Xamarin.Views
|
|||
public DirectAuthView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(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.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(x => x.UserNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.UserNameErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.PasswordErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.PasswordErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,9 +33,24 @@
|
|||
<Entry Grid.Column="0" Text="{Binding Address}" Placeholder="Please, enter host address" />
|
||||
<Entry Grid.Column="1" Text="{Binding Port}" Placeholder="Port" />
|
||||
</Grid>
|
||||
<Label x:Name="HostNameErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<Label x:Name="PortErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<Entry Text="{Binding Username}" Placeholder="Please, enter your login" />
|
||||
<Label x:Name="UserNameErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<Entry Text="{Binding Password}" IsPassword="True" Placeholder="Please, enter your password" />
|
||||
<Label x:Name="PasswordErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<controls:AccentButton Command="{Binding Login}" Text="Login" />
|
||||
<Label x:Name="FormErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage.Content>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
using ReactiveUI.XamForms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
|
@ -11,7 +15,35 @@ namespace Camelotia.Presentation.Xamarin.Views
|
|||
public HostAuthView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindValidation(ViewModel, x => x.Address, x => x.HostNameErrorLabel.Text)
|
||||
.DisposeWith(disposables);
|
||||
this.BindValidation(ViewModel, x => x.Port, x => x.PortErrorLabel.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.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(x => x.HostNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.HostNameErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.PortErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.PortErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.UserNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.UserNameErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.PasswordErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.PasswordErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
Title="Loading..."
|
||||
mc:Ignorable="d">
|
||||
<d:ContentPage.BindingContext>
|
||||
<!-- ReSharper disable once Xaml.InvalidType -->
|
||||
<designTime:DesignTimeMainViewModel />
|
||||
</d:ContentPage.BindingContext>
|
||||
</rxui:ReactiveNavigationPage>
|
|
@ -26,6 +26,9 @@
|
|||
TextColor="Red"
|
||||
Margin="0, 15" />
|
||||
<Entry Text="{Binding NewName}" Placeholder="New file name" />
|
||||
<Label x:Name="FileNameErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3*" />
|
||||
|
@ -40,6 +43,9 @@
|
|||
Margin="0, 10"
|
||||
Text="Close" />
|
||||
</Grid>
|
||||
<Label x:Name="FormErrorLabel"
|
||||
Style="{StaticResource ErrorLabelStyle}"
|
||||
VerticalOptions="Start" />
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage.Content>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Formatters;
|
||||
using ReactiveUI.XamForms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
|
@ -11,7 +15,20 @@ namespace Camelotia.Presentation.Xamarin.Views
|
|||
public RenameFileView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables => { });
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.BindValidation(ViewModel, x => x.NewName, x => x.FileNameErrorLabel.Text)
|
||||
.DisposeWith(disposables);
|
||||
this.BindValidation(ViewModel, x => x.FormErrorLabel.Text, new SingleLineFormatter(Environment.NewLine))
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(x => x.FileNameErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FileNameErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(x => x.FormErrorLabel.Text, text => !string.IsNullOrWhiteSpace(text))
|
||||
.BindTo(this, x => x.FormErrorLabel.IsVisible)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,9 +10,9 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI" Version="11.5.35" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="11.5.35" />
|
||||
<PackageReference Include="ReactiveUI.Validation" Version="1.6.4" />
|
||||
<PackageReference Include="ReactiveUI" Version="12.1.1" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="12.1.1" />
|
||||
<PackageReference Include="ReactiveUI.Validation" Version="1.8.6" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -6,7 +6,7 @@ using ReactiveUI.Validation.Helpers;
|
|||
|
||||
namespace Camelotia.Presentation.DesignTime
|
||||
{
|
||||
public class DesignTimeCreateFolderViewModel : ReactiveValidationObject<DesignTimeCreateFolderViewModel>, ICreateFolderViewModel
|
||||
public class DesignTimeCreateFolderViewModel : ReactiveValidationObject, ICreateFolderViewModel
|
||||
{
|
||||
public DesignTimeCreateFolderViewModel() => this.ValidationRule(x => x.Name, name => false, "Validation error.");
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ using ReactiveUI.Validation.Helpers;
|
|||
|
||||
namespace Camelotia.Presentation.DesignTime
|
||||
{
|
||||
public class DesignTimeDirectAuthViewModel : ReactiveValidationObject<DesignTimeDirectAuthViewModel>, IDirectAuthViewModel
|
||||
public class DesignTimeDirectAuthViewModel : ReactiveValidationObject, IDirectAuthViewModel
|
||||
{
|
||||
public DesignTimeDirectAuthViewModel() => this.ValidationRule(x => x.Username, name => false, "Validation error.");
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ using ReactiveUI.Validation.Helpers;
|
|||
|
||||
namespace Camelotia.Presentation.DesignTime
|
||||
{
|
||||
public class DesignTimeHostAuthViewModel : ReactiveValidationObject<DesignTimeHostAuthViewModel>, IHostAuthViewModel
|
||||
public class DesignTimeHostAuthViewModel : ReactiveValidationObject, IHostAuthViewModel
|
||||
{
|
||||
public DesignTimeHostAuthViewModel() => this.ValidationRule(x => x.Username, name => false, "Validation error.");
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ using ReactiveUI.Validation.Helpers;
|
|||
|
||||
namespace Camelotia.Presentation.DesignTime
|
||||
{
|
||||
public class DesignTimeRenameFileViewModel : ReactiveValidationObject<DesignTimeRenameFileViewModel>, IRenameFileViewModel
|
||||
public class DesignTimeRenameFileViewModel : ReactiveValidationObject, IRenameFileViewModel
|
||||
{
|
||||
public DesignTimeRenameFileViewModel() => this.ValidationRule(x => x.NewName, name => false, "Validation error.");
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
using System.ComponentModel;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Abstractions;
|
||||
|
||||
namespace Camelotia.Presentation.Interfaces
|
||||
{
|
||||
public interface ICreateFolderViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
|
||||
public interface ICreateFolderViewModel :
|
||||
INotifyPropertyChanged,
|
||||
INotifyDataErrorInfo,
|
||||
IValidatableViewModel,
|
||||
IReactiveObject
|
||||
{
|
||||
bool IsLoading { get; }
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
using System.ComponentModel;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Abstractions;
|
||||
|
||||
namespace Camelotia.Presentation.Interfaces
|
||||
{
|
||||
public interface IDirectAuthViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
|
||||
public interface IDirectAuthViewModel :
|
||||
INotifyPropertyChanged,
|
||||
INotifyDataErrorInfo,
|
||||
IValidatableViewModel,
|
||||
IReactiveObject
|
||||
{
|
||||
string Username { get; set; }
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Abstractions;
|
||||
|
||||
namespace Camelotia.Presentation.Interfaces
|
||||
{
|
||||
public interface IHostAuthViewModel : IDirectAuthViewModel
|
||||
public interface IHostAuthViewModel :
|
||||
IDirectAuthViewModel,
|
||||
IValidatableViewModel,
|
||||
IReactiveObject
|
||||
{
|
||||
string Address { get; set; }
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
using System.ComponentModel;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Abstractions;
|
||||
|
||||
namespace Camelotia.Presentation.Interfaces
|
||||
{
|
||||
public interface IRenameFileViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
|
||||
public interface IRenameFileViewModel :
|
||||
INotifyPropertyChanged,
|
||||
INotifyDataErrorInfo,
|
||||
IValidatableViewModel,
|
||||
IReactiveObject
|
||||
{
|
||||
bool IsLoading { get; }
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Camelotia.Presentation.ViewModels
|
|||
{
|
||||
public delegate ICreateFolderViewModel CreateFolderViewModelFactory(IProviderViewModel providerViewModel);
|
||||
|
||||
public sealed class CreateFolderViewModel : ReactiveValidationObject<CreateFolderViewModel>, ICreateFolderViewModel
|
||||
public sealed class CreateFolderViewModel : ReactiveValidationObject, ICreateFolderViewModel
|
||||
{
|
||||
private readonly ObservableAsPropertyHelper<string> _errorMessage;
|
||||
private readonly ObservableAsPropertyHelper<bool> _hasErrorMessage;
|
||||
|
|
|
@ -11,7 +11,7 @@ using ReactiveUI.Validation.Helpers;
|
|||
|
||||
namespace Camelotia.Presentation.ViewModels
|
||||
{
|
||||
public sealed class DirectAuthViewModel : ReactiveValidationObject<DirectAuthViewModel>, IDirectAuthViewModel
|
||||
public sealed class DirectAuthViewModel : ReactiveValidationObject, IDirectAuthViewModel
|
||||
{
|
||||
private readonly ObservableAsPropertyHelper<string> _errorMessage;
|
||||
private readonly ObservableAsPropertyHelper<bool> _hasErrorMessage;
|
||||
|
|
|
@ -12,7 +12,7 @@ using VkNet.Enums;
|
|||
|
||||
namespace Camelotia.Presentation.ViewModels
|
||||
{
|
||||
public sealed class HostAuthViewModel : ReactiveValidationObject<HostAuthViewModel>, IHostAuthViewModel
|
||||
public sealed class HostAuthViewModel : ReactiveValidationObject, IHostAuthViewModel
|
||||
{
|
||||
private readonly ObservableAsPropertyHelper<string> _errorMessage;
|
||||
private readonly ObservableAsPropertyHelper<bool> _hasErrorMessage;
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Camelotia.Presentation.ViewModels
|
|||
{
|
||||
public delegate IRenameFileViewModel RenameFileViewModelFactory(IProviderViewModel providerViewModel);
|
||||
|
||||
public sealed class RenameFileViewModel : ReactiveValidationObject<RenameFileViewModel>, IRenameFileViewModel
|
||||
public sealed class RenameFileViewModel : ReactiveValidationObject, IRenameFileViewModel
|
||||
{
|
||||
private readonly ObservableAsPropertyHelper<bool> _hasErrorMessage;
|
||||
private readonly ObservableAsPropertyHelper<string> _errorMessage;
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DynamicData" Version="6.17.14" />
|
||||
<PackageReference Include="akavache" Version="6.10.20" />
|
||||
<PackageReference Include="FluentFTP" Version="32.4.7" />
|
||||
<PackageReference Include="Google.Apis.Drive.v3" Version="1.49.0.2093" />
|
||||
<PackageReference Include="akavache" Version="7.1.1" />
|
||||
<PackageReference Include="FluentFTP" Version="33.0.2" />
|
||||
<PackageReference Include="Google.Apis.Drive.v3" Version="1.49.0.2117" />
|
||||
<PackageReference Include="Octokit" Version="0.48.0" />
|
||||
<PackageReference Include="ssh.net" Version="2016.1.0" />
|
||||
<PackageReference Include="System.Reactive" Version="4.4.1" />
|
||||
<PackageReference Include="VkNet" Version="1.56.0" />
|
||||
<PackageReference Include="VkNet" Version="1.57.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="ReactiveUI.Testing" Version="11.5.35" />
|
||||
<PackageReference Include="ReactiveUI.Testing" Version="12.1.1" />
|
||||
<PackageReference Include="NSubstitute" Version="4.2.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
|
|
Загрузка…
Ссылка в новой задаче