Environment

Product Version 2018.3.1122
Product DataForm for Xamarin

Description

In general, RadDataForm works with simple property types (string, int, long) and when you are using a custom type - the native Data Form is not sure what native type corresponds to the one you are using so it disregards the property. With this in mind, we have introduced a mechanism that maps the property declared in Xamarin.Forms to a native one. Below are the needed steps to enable this on Android and iOS.

Solution

First, create the custom property you will use inside the DataForm PickerEditor:

public class City
{
    public City(string name)
    {
        this.Name = name;
    }
    public string Name { get; set; }
    public override bool Equals(object obj)
    {
        return this.Name.Equals((obj as City)?.Name);
    }
}

Create a sample SourceItem class which will be the Source of RadDataForm, it has a property of type City:

public class SourceItem
{
    [DisplayOptions(Header = "Name")]
    public string Name { get; set; }

    [DisplayOptions(Header = "City")]
    public City City { get; set; }
}

Add a simple RadDataForm definition to your page:

<telerikInput:RadDataForm x:Name="dataForm" />

Add some code for setting its Source and registering the PickerEditor in code-behind. In addition, you would need to supply a PropertyDataSourceProvider for the Picker ItemsSource:

this.dataForm.Source = new SourceItem();
this.dataForm.RegisterEditor(nameof(SourceItem.City), EditorType.PickerEditor);
this.dataForm.PropertyDataSourceProvider = new CityDataSourceProvider();

Here is the provider:

public class CityDataSourceProvider : PropertyDataSourceProvider
{
    public override IList GetSourceForKey(object key)
    {
        if (key.ToString().Equals("City"))
        {
            return new ObservableCollection<City>
            {
                new City("Tokyo"),
                new City("London"),
                new City("Paris"),
                new City("New York City"),
                new City("Brussels"),
                new City("Berlin"),
                new City("Sofia")
            };
            }
        return null;
    }
}

That's all on the shared project.

Now, let's continue the implementation with the Android project. The City type should be converted to a Java type through a Telerik.XamarinForms.Common.Android.TypeRegister inside the MainActivity.cs file of the Android project (call it before LoadApplication):

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        ...
        TypeRegister.Register(typeof(City), typeof(JavaCity), new MyTypeConverter());
        LoadApplication(new App());
    }
    ...
}

Add the needed MyTypeConverter and JavaCity classes:

public class JavaCity : ConvertibleObject<City>
{
    public JavaCity(City instance) : base(instance)
    {
    }
    // the display value in editor
    public override string ToString()
    {
        return Instance.Name;
    }
}

public class MyTypeConverter : ITypeConverter
{
    public Java.Lang.Object Convert(object sourceObject)
    {
        return new JavaCity((City)sourceObject);
    }
    public object ConvertBack(Java.Lang.Object nativeObject)
    {
        return (nativeObject as JavaCity).Instance;
    }
}

Lastly, let's go to the iOS project. Again, go to AppDelegate.cs and add the needed code to convert the City type through Telerik.XamarinForms.Common.iOS.TypeRegister method:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    TypeRegister.Register(typeof(City), typeof(NSCity), new MyTypeConverter());
    return base.FinishedLaunching(app, options);
}

And here are the final bits:

public class NSCity : ConvertibleObject<City>
{
    public NSCity(City instance) : base(instance)
    {
    }
    // the display value in editor
    public override string Description
    {
        get
        {
            return Instance.Name;
        }
    }
}
public class MyTypeConverter : ITypeConverter
{
    public NSObject Convert(object sourceObject)
    {
        return new NSCity((City)sourceObject);
    }

    public object ConvertBack(NSObject nativeObject)
    {
        return (nativeObject as NSCity).Instance;
    }
}

Here is the DataForm while setting City property:

In this article
Not finding the help you need? Improve this article