Editing in Xamarin DataForm (SfDataForm)
17 Oct 202322 minutes to read
The data form supports several built-in editors.
Supported editors and associated DataFormItem
Editor name | Editor class | Data Type/Attribute | Input control loaded |
---|---|---|---|
Text | The String type property and any other type apart from the following specified cases. | ||
MultilineText | The String type property with multi line text. [DataType(DataType.MultilineText)] | ||
Numeric | The property of Int, Double, Float, Decimal, Long types and also its nullable property. | ||
Percent | The property of Int, Double, Float, Decimal, Long types and also its nullable property with [DataType(“Percent”)] attribute. | ||
Currency | The property of Int, Double, Float, Decimal, Long types and also its nullable property with [DataType(DataType.Currency)] attribute. | ||
Date | The DateTime type property and the property with [DataType(DataType.Date)] and [DataType(DataType.DateTime)] attributes. | ||
Time | The property with [DataType(DataType.Time)] attribute. | ||
NumericUpDown | Int or Double type property. | ||
Segment | Enum type property. | ||
Bool | Bool type property. | ||
Switch | Bool type property. | ||
Picker | Enum and List type property. [EnumDataTypeAttribute] | ||
DropDown | Enum and List type property. [EnumDataTypeAttribute] | ||
AutoComplete | Enum and List type property. [EnumDataTypeAttribute] | ||
Password | The String type property and property with [DataType(DataType.Password)] attribute. | ||
RadioGroup | Enum and List type property. [EnumDataTypeAttribute] | ||
MaskedEditText | The property with [DataType(DataType.PhoneNumber)] attribute. |
Changing editor for type
By default, the editors will be loaded based on the previous table. To change the editor for any type, use the RegisterEditor method and specify the type and editor.
dataForm.RegisterEditor(typeof(int), "NumericUpDown");
Here, the NumericUpDown
editor will be loaded for the integer type instead of numeric editor.
Changing editor for property
To change the editor for any property, use the RegisterEditor method and specify the property name and editor.
dataForm.RegisterEditor("IsAvailable", "Switch");
Here, the Switch editor will be loaded for the IsAvailable
property (bool type) instead of CheckBox
editor.
Customizing existing editor
The existing editors defined in the previous table can be customized by overriding the default editors.
Here, the DataFormTextEditor is customized to set different foreground for the FirstName property text editor.
public class CustomTextEditor : DataFormTextEditor
{
public CustomTextEditor(SfDataForm dataForm) : base(dataForm)
{
}
protected override void OnInitializeView(DataFormItem dataFormItem, Entry view)
{
if (dataFormItem.Name == "FirstName")
view.TextColor = Color.Green;
base.OnInitializeView(dataFormItem, view);
}
}
dataForm.RegisterEditor("Text", new CustomTextEditor(dataForm));
Creating new custom editor
Create the custom editor by overriding the DataFormEditor class.
Property settings, commit, data validation can be handled by overriding the required methods. Here, the Entry
is loaded for Age
editor.
public class CustomTextEditor : DataFormEditor<Entry>
{
public CustomTextEditor(SfDataForm dataForm) : base(dataForm)
{
}
protected override Entry OnCreateEditorView(DataFormItem dataFormItem)
{
return new Entry();
}
protected override void OnInitializeView(DataFormItem dataFormItem, Entry view)
{
base.OnInitializeView(dataFormItem, view);
view.Keyboard = Keyboard.Numeric;
this.OnUpdateValue(dataFormItem, view);
this.OnUpdateReadOnly(dataFormItem, view);
}
protected override void OnWireEvents(Entry view)
{
view.TextChanged += OnViewTextChanged;
view.Focused += OnViewFocused;
view.Unfocused += OnViewUnfocused;
}
private void OnViewPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnValidateValue(sender as Entry);
}
private void OnViewFocused(object sender, FocusEventArgs e)
{
var view = (sender as Entry);
view.TextColor = Color.Green;
}
protected override bool OnValidateValue(Entry view)
{
return this.DataForm.Validate("Age");
}
private void OnViewUnfocused(object sender, FocusEventArgs e)
{
var view = sender as Entry;
view.TextColor = Color.Red;
if (this.DataForm.CommitMode == Syncfusion.XForms.DataForm.CommitMode.LostFocus || this.DataForm.ValidationMode == ValidationMode.LostFocus)
this.OnValidateValue(view);
if (this.DataForm.CommitMode != Syncfusion.XForms.DataForm.CommitMode.LostFocus) return;
this.OnCommitValue(view);
OnValidateValue(sender as Entry);
}
private void OnViewTextChanged(object sender, TextChangedEventArgs e)
{
var view = sender as Entry;
if (DataForm.CommitMode == Syncfusion.XForms.DataForm.CommitMode.PropertyChanged || DataForm.ValidationMode == ValidationMode.PropertyChanged)
this.OnValidateValue(view);
if (this.DataForm.CommitMode != Syncfusion.XForms.DataForm.CommitMode.PropertyChanged) return;
this.OnCommitValue(view);
}
protected override void OnCommitValue(Entry view)
{
var dataFormItemView = view.Parent as DataFormItemView;
this.DataForm.ItemManager.SetValue(dataFormItemView.DataFormItem, view.Text);
}
protected override void OnUpdateValue(DataFormItem dataFormItem, Entry view)
{
var cellValue = this.DataForm.ItemManager.GetValue(dataFormItem);
if (cellValue != null && view.Text == cellValue.ToString())
return;
view.Text = cellValue == null ? string.Empty : cellValue.ToString();
}
protected override void OnUpdateReadOnly(DataFormItem dataFormItem, Entry view)
{
base.OnUpdateReadOnly(dataFormItem, view);
}
protected override void OnUnWireEvents(Entry view)
{
view.TextChanged -= OnViewTextChanged;
view.Focused -= OnViewFocused;
view.Unfocused -= OnViewUnfocused;
}
}
dataForm.RegisterEditor("numeric", new CustomTextEditor(dataForm));
dataForm.RegisterEditor("Age", "numeric");
dataForm.ValidationMode = ValidationMode.LostFocus;
You should manually commit the custom DataFormItem editor value by using OnCommitValue override method of DataFormEditor class on custom editor Value
or Focus changed
event which is used to update the custom editor value in respective property in DataObject based on dataform commit mode set.
Also , you should manually validate the custom editor value in by using OnValidateValue override method of DataFormEditor
class on custom editor Value
or Focus changed
event which is used to validate the custom editor value based on data form validation mode set . In the override method for OnValidateValue, you need to return DataForm.Validate(string) method in order to validate the particular data item.
Also, you should manually update the value to the custom editor by using OnUpdateValue override method of DataFormEditor
class on custom editor while bound the value from the Model class.
Support for Email editor
You can load the Email editor by changing KeyBoard
type in the AutoGeneratingDataFormItem event.
dataForm.AutoGeneratingDataFormItem += DataForm_AutoGeneratingDataFormItem;
private void DataForm_AutoGeneratingDataFormItem(object sender, AutoGeneratingDataFormItemEventArgs e)
{
if (e.DataFormItem != null && e.DataFormItem.Name == "Email")
(e.DataFormItem as DataFormTextItem).KeyBoard = Keyboard.Email;
}
Commit mode
The CommitMode determines when the value should be committed to the data object.
The supported commit modes are as follows:
- LostFocus
- PropertyChanged
- Explicit
<?xml version="1.0" encoding="utf-8" ?>
<?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:local="clr-namespace:GettingStarted"
xmlns:dataForm ="clr-namespace:Syncfusion.XForms.DataForm;assembly=Syncfusion.SfDataForm.XForms"
x:Class="GettingStarted.MainPage">
<ContentPage.Content>
<dataForm:SfDataForm x:Name="dataForm" CommitMode="LostFocus"/>
</ContentPage.Content>
</ContentPage>
dataForm.CommitMode = CommitMode.LostFocus;
LostFocus
If the commit mode is LostFocus, the value is committed when the editor lost its focus.
PropertyChanged
The value will be committed immediately when it is changed.
Explicit
The value should be committed manually by calling the SfDataForm.Commit or SfDataForm.Commit(propertyName) method.
The following code commits the value of all the properties in the data object:
dataForm.Commit();
To commit the specific property value, pass the property name as argument.
dataForm.Commit("Name");
Update editor value based on another editor
You can the update the editor value by using the SfDataForm.UpdateEditor method at runtime.
<?xml version="1.0" encoding="utf-8" ?>
<?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:local="clr-namespace:GettingStarted"
xmlns:dataForm ="clr-namespace:Syncfusion.XForms.DataForm;assembly=Syncfusion.SfDataForm.XForms"
x:Class="GettingStarted.MainPage">
<ContentPage.Content>
<dataForm:SfDataForm x:Name="dataForm"/>
</ContentPage.Content>
</ContentPage>
var expenseInfo = new ExpenseInfo();
expenseInfo.PropertyChanged += ExpenseInfo_PropertyChanged;
dataForm.DataObject = expenseInfo;
private void ExpenseInfo_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Budget" || e.PropertyName == "Expense")
{
var item = sender as ExpenseInfo;
item.Balance = item.Budget - item.Expense;
dataForm.UpdateEditor("Balance");
}
}
Here, the Balance property value is updated based on Budget and Expense properties. For updating value in editor, the UpdateEditor
method is called.
You can download the sample from here
Converter
To show the original value in different format or as different value, use the Converter attribute.
Changing original value of the DataForm property value using converter
Here, the original value is multiplied by 10 and shown in editor. While committing, it is divided by 10 and stored in the data object.
public class ValueConverterExt : IPropertyValueConverter
{
public object Convert(object value)
{
var amount = double.Parse(value.ToString());
return amount * 10;
}
public object ConvertBack(object value)
{
var amount = double.Parse(value.ToString());
return amount / 10;
}
}
private double? amount = 1000;
[Converter(typeof(ValueConverterExt))]
public double? Amount
{
get
{
return amount;
}
set
{
amount = value;
RaisePropertyChanged("Amount");
}
}
Using date editor for DateTimeOffset DataForm property data type
In SfDataForm, you cannot use date editor for DateTimeOffset
property data type. To overcome this, you need to use Converter
attribute to convert DateTimeOffset
to DateTime
value and vice-versa.
private DateTimeOffset displayDate;
[Converter(typeof(ValueConverterExt))]
public DateTimeOffset DisplayDate
{
get
{
return displayDate;
}
set
{
displayDate = value;
}
}
public class ValueConverterExt : IPropertyValueConverter
{
public object Convert(object value)
{
DateTime baseTime = new DateTime(2008, 6, 19, 7, 0, 0);
DateTime targetTime;
var dateTimeOffset = (DateTimeOffset)value;
dateTimeOffset = new DateTimeOffset(baseTime,
TimeZoneInfo.Local.GetUtcOffset(baseTime));
targetTime = dateTimeOffset.DateTime;
return targetTime;
}
public object ConvertBack(object value)
{
var dateTime = (DateTime)value;
dateTime = new DateTime(2008, 6, 19, 7, 0, 0);
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
DateTimeOffset dateTimeOffset = dateTime;
return dateTimeOffset;
}
}
You can download the source code of this demo from here DateTimeOffsetConverter
Disable editing
You can disable editing by setting the IsReadOnly property of the data form.
<?xml version="1.0" encoding="utf-8" ?>
<?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:local="clr-namespace:GettingStarted"
xmlns:dataForm ="clr-namespace:Syncfusion.XForms.DataForm;assembly=Syncfusion.SfDataForm.XForms"
x:Class="GettingStarted.MainPage">
<ContentPage.Content>
<dataForm:SfDataForm x:Name="dataForm" IsReadOnly="True"/>
</ContentPage.Content>
</ContentPage>
dataForm.IsReadOnly = true;
You can also change the editing behavior by setting the IsReadOnly property of the DataFormItem.
dataForm.AutoGeneratingDataFormItem += DataForm_AutoGeneratingDataFormItem;
private void DataForm_AutoGeneratingDataFormItem(object sender, AutoGeneratingDataFormItemEventArgs e)
{
if (e.DataFormItem != null)
{
if (e.DataFormItem.Name == "Salary")
e.DataFormItem.IsReadOnly = true;
}
}
You can also change the editing behavior at runtime.
private void Button_Click(object sender, System.EventArgs e)
{
var dataFormItem = dataForm.ItemManager.DataFormItems["FirstName"];
dataFormItem.IsReadOnly = true;
}
NOTE
DataFormItem.IsReadOnly takes higher priority than SfDataForm.IsReadOnly.
Two-way data binding
When the DataForm business object properties are updated with two-way data binding support, the value will sync with underlying DataForm editors.
To enable two-way data binding support, set the value of NotifyPropertyChanges property to true in DataForm.
<?xml version="1.0" encoding="utf-8" ?>
<?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:local="clr-namespace:GettingStarted"
xmlns:dataForm ="clr-namespace:Syncfusion.XForms.DataForm;assembly=Syncfusion.SfDataForm.XForms"
x:Class="GettingStarted.MainPage">
<ContentPage.Content>
<dataForm:SfDataForm x:Name="dataForm" NotifyPropertyChanges="True"/>
</ContentPage.Content>
</ContentPage>
dataForm.NotifyPropertyChanges = true;
You can download the entire source code of this demo from here Two-wayDataBinding
See also
How to save or cancel the edited DataForm data in Xamarin.Forms (SfDataForm)
How to programmatically implement converter to Xamarin.Forms DataForm (SfDataForm)
How to register common editor for same data type properties in Xamarin.Forms DataForm business object
How to change the editor visibility based on another editor in Xamarin.Forms DataForm (SfDataForm)
How to update editor value based on another editor in Xamarin.Forms DataForm (SfDataForm)