Component Based UI vs View-ViewModel
Xamarin Forms promotes the separation between the View (usually written in xaml) and the Model (usually written in c#). This pattern is called View-ViewModel and has been historically adopted by a lot of UI framework like WPF/SL, angular etc.
Recently Component based pattern has gained much popularity thanks to ReactJS and Flutter.
Let's take for an example a login page written in Xamarin Forms composed of a MainPage (XAML) and a ViewModel MainPageViewModel (c#):
Copy <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="XamarinApp1.MainPage">
<StackLayout
VerticalOptions="Center"
HorizontalOptions="Center">
<Entry Placeholder="Username" Text="{Binding Username}" />
<Entry Placeholder="Password" Text="{Binding Password}" />
<Button Text="Login" Command="{Binding LoginCommand}" />
</StackLayout>
</ContentPage>
Copy public class MainPageViewModel : BindableObject
{
private string _username;
public string Username
{
get => _username;
set
{
if (_username != value)
{
_username = value;
OnPropertyChanged();
LoginCommand.ChangeCanExecute();
}
}
}
private string _password;
public string Password
{
get => _password;
set
{
if (_password != value)
{
_password = value;
OnPropertyChanged();
LoginCommand.ChangeCanExecute();
}
}
}
private Command _loginCommand;
public Command LoginCommand
{
get
{
_loginCommand = _loginCommand ?? new Command(OnLogin, () => !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password));
return _loginCommand;
}
}
private void OnLogin()
{
//Username contains username and Password contains password
//make login..
}
}
ReactorUI Component Based
Copy public class MainPageState : IState
{
public string Username { get; set; }
public string Password { get; set; }
}
public class MainPage : RxComponent<MainPageState>
{
public override VisualNode Render()
{
return new RxContentPage()
{
new RxStackLayout()
{
new RxEntry()
.Placeholder("Username")
.OnTextChanged((s,e)=> SetState(_ => _.Username = e.NewTextValue)),
new RxEntry()
.Placeholder("Password")
.OnTextChanged((s,e)=> SetState(_ => _.Password = e.NewTextValue)),
new RxButton("Login")
.IsEnabled(!string.IsNullOrWhiteSpace(State.Username) && !string.IsNullOrWhiteSpace(State.Password))
.OnClick(OnLogin)
}
.VCenter()
.HCenter()
};
}
private void OnLogin()
{
//use State.Username and State.Password to login...
}
}