Editing

SfDataForm provides support for several built-in editors.

Supported editors and associated DataFormItem

Editor name Editor class Data Type/Attribute Input control loaded
Text

DataFormTextEditor

Property of type string and any other type apart from below specified cases.

UITextField

MultilineText

DataFormMultiLineTextEditor

Property of string type with Multiline text. [DataType(DataType.Multiline)]

UITextView

Numeric

DataFormNumericEditor

Property of type int, double, float, decimal, long types and its nullable also properties with below attributes.

SfNumericTextBox

Percent

DataFormNumericEditor

Property of type int, double, float, decimal, long types and its nullable also properties with below attributes. [DataType(“Percent”)].

SfNumericTextBox

Currency

DataFormNumericEditor

Property of type int, double, float, decimal, long types and its nullable also properties with below attributes. [DataType(DataType.Currency)].

SfNumericTextBox

Date

DataFormDateEditor

Property of type DateTime and Property with below attribute [DataType(DataType.Date)]. [DataType(DataType.DateTime)]

SfDatePicker

Time

DataFormTimeEditor

Property with below attribute. [DataType(DataType.Time)].

SfTimePicker

NumericUpDown

DataFormNumericUpDownEditor

Property of type Int or Double.

SfNumericUpDown

Segment

DataFormSegmentedEditor

Property of type enum.

UISegmentedControl

Bool

DataFormSwitchEditor

Property of type bool

UISwitch

Picker

DataFormPickerEditor

Property of type enum and list. [EnumDataTypeAttribute]

SfPicker

Password

DataFormPasswordEditor

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

UITextField

Changing editor for type

By default, editors will be loaded based on above table. If you want to change the editor for any type, you need to use RegisterEditor method and specify type and editor.

dataForm.RegisterEditor(typeof(int), "NumericUpDown");

Here, NumericUpDown editor will be loaded for integer type instead of numeric editor.

Changing editor for property

If you want to change the editor for any property, you need to use RegisterEditor method and specify property name and editor.

dataForm.RegisterEditor("Name", "DropDown");

Here, Switch editor will be loaded for Name property (Enum type) instead of Picker editor.

Customizing existing editor

You can customize the existing editors defined in above table, by overriding default editors.

Here,DataFormTextEditor is customized to set different foreground for FirstName property text editor.

public class CustomTextEditor : DataFormTextEditor
{
    public CustomTextEditor(SfDataForm dataForm) : base(dataForm)
    {
    }

    protected override void OnInitializeView(DataFormItem dataFormItem, UITextField view)
    {
        if (dataFormItem.Name == "FirstName")
            view.TextColor = UIColor.Green;
        base.OnInitializeView(dataFormItem, view);
    }
}
dataForm.RegisterEditor("Text", new CustomTextEditor(dataForm));

Customizing existing editor of data form item in Xamarin.iOS DataForm

Creating new custom editor

You can create custom editor by overriding DataFormEditor class.
Property settings, commit, data validation can be handled by overriding required methods. Here, UITextField is loaded for Age editor.

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

	protected override UITextField OnCreateEditorView()
	{
		return new UITextField();
	}
	protected override void OnInitializeView(DataFormItem dataFormItem, UITextField view)
	{
		base.OnInitializeView(dataFormItem, view);
	}

	protected override void OnWireEvents(UITextField view)
	{
		view.ValueChanged+= OnViewValueChanged;
	}

	private void OnViewValueChanged(object sender, EventArgs e)
	{
		var view = sender as UITextField;
		if (DataForm.CommitMode == CommitMode.PropertyChanged || DataForm.ValidationMode == ValidationMode.PropertyChanged)
			this.OnValidateValue(view);
		if (this.DataForm.CommitMode != CommitMode.PropertyChanged) return;
		this.OnCommitValue(view);
		OnValidateValue(sender as UITextField);
	}


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


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

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

	protected override void OnUnWireEvents(UITextField view)
	{
		view.ValueChanged -= OnViewValueChanged;
	}
}

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

Support for Email editor

You can load Email editor by changing KeyBoardType in 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).KeyBoardType = UIKeyboardType.EmailAddress;
    }
}

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

Commit mode

CommitMode determines when the value should be committed to data object.

Below are the supported commit modes.

  • LostFocus
  • PropertyChanged
  • Explicit
dataForm.CommitMode = CommitMode.LostFocus;

LostFocus

If the commit mode is LostFocus, value is committed when the editor lost its focus.

PropertyChanged

Value is committed immediately when it is changed.

Explicit

Value should be committed manually by calling SfDataForm.Commit or SfDataForm.Commit(propertyName) method.

Below code commits the value of all the properties in data object.

dataForm.Commit();

If you want to commit specific property value, you need to pass property name as argument.

dataForm.Commit("Name");

Update editor value based on another editor

You can the update the editor value by using 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, Balance property value is updated based on Budget and Expense properties. For updating value in editor, UpdateEditor method is called.
You can download the sample from here.

Converter

If you want to show the original value in different format or as different value, you need to use Converter attribute.

Changing original value of the DataForm property value using converter

Here, original value is multiplied by 10 and shown in editor. While committing, it is divided by 10 and stored in 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 edit by setting IsReadOnly property of SfDataForm.

dataForm.IsReadOnly = true;

You can also change the editing behavior by setting IsReadOnly property of 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 change the editing behavior at runtime also.

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