I have the following code in my Xamarin Forms project (it is from the official sample project of Syncfusion).
ViewModel:
[Preserve(AllMembers = true)]
public class RecipientInfoViewModel : INotifyPropertyChanged
{
private RecipientInfo recipientInfo;
private bool isVisible;
public RecipientInfoViewModel()
{
this.recipientInfo = new RecipientInfo();
this.isVisible = true;
this.CommitCommand = new Command<object>(this.OnCommit);
}
public event PropertyChangedEventHandler PropertyChanged;
public RecipientInfo RecipientInfo
{
get { return this.recipientInfo; }
set { this.recipientInfo = value; }
}
public bool IsVisible
{
get
{
return this.isVisible;
}
set
{
this.isVisible = value;
this.OnPropertyChanged("IsVisible");
}
}
public Command<object> CommitCommand { get; set; }
/// <summary>
/// Commits the value of the specific editor to corresponding property in the business object.
/// </summary>
/// <param name="dataForm">The corresponding DataForm.</param>
private void OnCommit(object dataForm)
{
var dataFormLayout = dataForm as Syncfusion.XForms.DataForm.SfDataForm;
var isValid = dataFormLayout.Validate();
dataFormLayout.Commit();
if (!isValid)
{
App.Current.MainPage.DisplayAlert("Alert", "Please enter valid details", "Ok");
return;
}
App.Current.MainPage.DisplayAlert("Alert", "Money Transferred", "Ok");
dataFormLayout.IsReadOnly = true;
this.IsVisible = false;
}
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sync="clr-namespace:Syncfusion.XForms.DataForm;assembly=Syncfusion.SfDataForm.XForms"
xmlns:local2="clr-namespace:TestProject.Helpers"
xmlns:local="clr-namespace:TestProject.ViewModels"
x:Class="TestProject.Views.GettingStarted">
<ContentPage.BindingContext>
<local:RecipientInfoViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<sync:SfDataForm x:Name="dataForm" LayoutOptions="TextInputLayout" ValidationMode="Explicit" DataObject="{Binding RecipientInfo}">
<sync:SfDataForm.Behaviors>
<local2:SfDataFormGettingStartedBehavior />
</sync:SfDataForm.Behaviors>
</sync:SfDataForm>
<Button x:Name="transferMoney" Grid.Row="1" Text="Transfer Money" TextColor="#FFFFFF"
WidthRequest="150" HeightRequest="40" BackgroundColor="#2196F3" HorizontalOptions="Center"
VerticalOptions="Center"
Command="{Binding Path=BindingContext.CommitCommand, Source={x:Reference Name=dataForm}}"
CommandParameter="{Binding Source={x:Reference Name=dataForm}}"
IsVisible="{Binding IsVisible, Mode=TwoWay}" />
</Grid>
</ContentPage.Content>
</ContentPage>
Model:
/// <summary>
/// Describes the possible account type.
/// </summary>
[Preserve(AllMembers = true)]
public enum AccountType
{
/// <summary>
/// Represents savings account type.
/// </summary>
Savings,
/// <summary>
/// Represents current account type.
/// </summary>
Current,
/// <summary>
/// Represents overdraft account type.
/// </summary>
Overdraft,
/// <summary>
/// Represents cashcredit account type.
/// </summary>
CashCredit,
/// <summary>
/// Represents loan account type.
/// </summary>
LoanAccount,
/// <summary>
/// Represents NRE account type.
/// </summary>
NRE,
/// <summary>
/// Represents cardpayment type.
/// </summary>
CardPayment
}
/// <summary>
/// Represents the recipient information of the data form getting started sample.
/// </summary>
[Preserve(AllMembers = true)]
public class RecipientInfo : INotifyPropertyChanged, INotifyDataErrorInfo
{
#region Fields
/// <summary>
/// Represents the account number of the recipient information.
/// </summary>
private string accountNumber;
/// <summary>
/// Represents the second account number of the recipient information.
/// </summary>
private string accountNumber1;
/// <summary>
/// Represents the email id of the recipient information.
/// </summary>
private string email;
/// <summary>
/// Represents the amount of the recipient information.
/// </summary>
private double? amount = null;
/// <summary>
/// Represents the name of the recipient information.
/// </summary>
private string name;
/// <summary>
/// Represents the swift of the recipient information.
/// </summary>
private string swift;
/// <summary>
/// Represents the terms and conditions of the recipient information.
/// </summary>
private bool agree;
/// <summary>
/// Represents the password of the recipient information.
/// </summary>
private string password;
/// <summary>
/// Represents the account type of the recipient information.
/// </summary>
private AccountType accountType;
/// <summary>
/// Represents the immutable email regular expression.
/// </summary>
private Regex emailRegex = new Regex(@"^([w.-]+)@([w-]+)((.(w){2,3})+)$");
/// <summary>
/// Represents a collection of keys and values.
/// </summary>
private Dictionary<string, List<string>> propErrors = new Dictionary<string, List<string>>();
/// <summary>
/// Represents a immutable regular expression.
/// </summary>
private Regex swiftRegex = new Regex("^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$");
#endregion Fields
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="RecipientInfo"/> class.
/// </summary>
public RecipientInfo()
{
}
/// <summary>
/// Represents the method that will handle when a property is changed on a component.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Represents the method that will handle when a Errors are changed.
/// </summary>
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
#endregion Constructor
#region Public Properties
/// <summary>
/// Gets a value indicating whether recipient information contains errors.
/// </summary>
////[Display(AutoGenerateField = false)]
public bool HasErrors
{
get
{
var propErrorsCount = this.propErrors.Values.FirstOrDefault(r => r.Count > 0);
if (propErrorsCount != null)
{
return true;
}
else
{
return false;
}
}
}
/// <summary>
/// Gets or sets the account number field.
/// </summary>
[Display(ShortName = "Account number")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter account number.")]
public string AccountNumber
{
get
{
return this.accountNumber;
}
set
{
if (value != this.AccountNumber)
{
this.accountNumber = value;
this.RaisePropertyChanged("AccountNumber");
this.RaiseErrorChanged("AccountNumber");
}
}
}
/// <summary>
/// Gets or sets the first account number field.
/// </summary>
[Display(ShortName = "Re-enter account number")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Please re-enter account number.")]
public string AccountNumber1
{
get
{
return this.accountNumber1;
}
set
{
if (value != this.AccountNumber1)
{
this.accountNumber1 = value;
this.RaisePropertyChanged("AccountNumber1");
this.RaiseErrorChanged("AccountNumber1");
}
}
}
/// <summary>
/// Gets or sets the SWIFT field.
/// </summary>
[Display(Order = 0, ShortName = "SWIFT code", Prompt = "Enter 8 or 11 upper case letters")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter the SWIFT code.")]
[DisplayOptions(ValidMessage = "Name length is enough")]
public string SWIFT
{
get
{
return this.swift;
}
set
{
this.swift = value;
this.RaisePropertyChanged("SWIFT");
this.RaiseErrorChanged("SWIFT");
}
}
/// <summary>
/// Gets or sets the name field.
/// </summary>
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter the name.")]
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
this.RaisePropertyChanged("Name");
this.RaiseErrorChanged("Name");
}
}
/// <summary>
/// Gets or sets the email field.
/// </summary>
[Display(ShortName = "Email")]
[EmailAddress(ErrorMessage = "Please enter a valid e-mail id.")]
public string Email
{
get
{
return this.email;
}
set
{
this.email = value;
this.RaisePropertyChanged("Email");
this.RaiseErrorChanged("Email");
}
}
/// <summary>
/// Gets or sets the ammount field.
/// </summary>
[Display(ShortName = "Amount")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter the amount.")]
public double? Amount
{
get
{
return this.amount;
}
set
{
this.amount = value;
this.RaisePropertyChanged("Amount");
this.RaiseErrorChanged("Amount");
}
}
/// <summary>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…