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...
}
}