Editing

3 Sep 202015 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

DataFormTextEditor

The String type property and any other type apart from the following specified cases.

EditText

MultilineText

DataFormMultiLineTextEditor

The String type property with multi line text. [DataType(DataType.Multiline)]

EditText

Numeric

DataFormNumericEditor

The property of Int, Double, Float, Decimal, Long types and also its nullable property.

SfNumericTextBox

Percent

DataFormNumericEditor

The property of Int, Double, Float, Decimal, Long types and also its nullable property with [DataType(“Percent”)] attribute.

SfNumericTextBox

Currency

DataFormNumericEditor

The property of Int, Double, Float, Decimal, Long types and also its nullable property with [DataType(DataType.Currency)] attribute.

SfNumericTextBox

Date

DataFormDateEditor

The DateTime type property and the property with [DataType(DataType.Date)] and [DataType(DataType.DateTime)] attributes.

SfDatePicker

Time

DataFormTimeEditor

The property with [DataType(DataType.Time)] attribute.

SfTimePicker

NumericUpDown

DataFormNumericUpDownEditor

Int or Double type property.

SfNumericUpDown

Segment

DataFormSegmentedEditor

Enum type property.

RadioGroup

Bool

DataFormCheckBoxEditor

Bool type property.

CheckBox

Switch

DataFormSwitchEditor

Bool type property.

Switch

Picker

DataFormPickerEditor

Enum and List type property. [EnumDataTypeAttribute]

SfPicker

DropDown

DataFormDropDownEditor

Enum and List type property. [EnumDataTypeAttribute]

Spinner

Password

DataFormPasswordEditor

The String type property and property with [DataType(DataType.Password)] attribute.

EditText

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, EditText view)
    {
        if (dataFormItem.Name == "FirstName")
            view.SetTextColor(Color.Green);
        base.OnInitializeView(dataFormItem, view);
    }
}

dataForm.RegisterEditor("Text", new CustomTextEditor(dataForm));

Customizing existing editor of data form item in Xamarin.Android 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 EditText is loaded for Age editor.

public class CustomTextEditor : DataFormEditor<EditText>
{
	public CustomTextEditor(SfDataForm dataForm) : base(dataForm)
	{
	}

	protected override EditText OnCreateEditorView()
	{
		return new EditText(this.dataForm.Context);
	}
	protected override void OnInitializeView(DataFormItem dataFormItem, EditText view)
	{
		base.OnInitializeView(dataFormItem, view);
	}

	protected override void OnWireEvents(EditText view)
	{
		view.TextChanged += OnViewTextChanged;
		view.FocusChange += OnViewFocusChange;
	}

	private void OnViewFocusChange(object sender, View.FocusChangeEventArgs e)
	{
		var view = sender as EditText;
		view.SetTextColor(Color.Red);

		if (this.DataForm.CommitMode == CommitMode.LostFocus || this.DataForm.ValidationMode == ValidationMode.LostFocus)
			this.OnValidateValue(view);
		if (this.DataForm.CommitMode != CommitMode.LostFocus) return;
		this.OnCommitValue(view);
		OnValidateValue(sender as EditText);
	}

	private void OnViewTextChanged(object sender, Android.Text.TextChangedEventArgs e)
	{
		var view = sender as EditText;
		if (DataForm.CommitMode == CommitMode.PropertyChanged || DataForm.ValidationMode == ValidationMode.PropertyChanged)
			this.OnValidateValue(view);
		if (this.DataForm.CommitMode != CommitMode.PropertyChanged) return;
		this.OnCommitValue(view);
	}

	private void OnViewPropertyChanged(object sender, PropertyChangedEventArgs e)
	{
		OnValidateValue(sender as EditText);
	}

	protected override bool OnValidateValue(EditText view)
	{
		return this.DataForm.Validate("Age");
	}

	protected override void OnCommitValue(EditText view)
	{
		var dataFormItemView = view.Parent as DataFormItemView;
		this.DataForm.ItemManager.SetValue(dataFormItemView.DataFormItem, view.Text);
	}

	protected override void OnUnWireEvents(EditText view)
	{
		view.TextChanged -= OnViewTextChanged;
		view.FocusChange -= OnViewFocusChange;
	}
}

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.

Creating custom editor for the data form item in Xamarin.Android DataForm

Support for Email editor

You can load the Email editor by changing input type in the AutoGeneratingDataFormItem event.

dataForm.AutoGeneratingDataFormItem += DataForm_AutoGeneratingDataFormItem;
private void DataForm_AutoGeneratingDataFormItem(object sender, AutoGeneratingDataFormItemEventArgs e)
{
    if (e.DataFormItem.Name == "Email")
        (e.DataFormItem as DataFormTextItem).InputType = Android.Text.InputTypes.TextVariationEmailAddress;
}

Loading Email editor to the data form item in Xamarin.Android DataForm

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

var expenseInfo = new ExpenseInfo();
expenseInfo.PropertyChanged += ExpenseInfo_PropertyChanged;
dataForm.DataObject = expenseInfo;
SetContentView(dataForm);

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.

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.

You can also have option to define the editing behavior from SfDataForm.DataObject definition using the ReadOnly attribute and EditableAttribute.

private double? balance;
[ReadOnly(true)]
public double? Balance
{
    get
    {
        return balance;
    }
    set
    {
        balance = value;
        RaisePropertyChanged("Balance");
    }
}
private double? balance;
[Editable(false)]
public double? Balance
{
    get
    {
        return balance;
    }
    set
    {
        balance = value;
        RaisePropertyChanged("Balance");
    }
}

You can also define the editing behavior by defining the SfDataForm.DataObject fields definition without setter or with private set.

private double? balance;
public double? Balance
{
    get
    {
        return balance;
    }    
}
private double? balance;
public double? Balance
{
    get
    {
        return balance;
    }
    private set
    {
        balance = value;
    }
}