New to Telerik UI for Xamarin? Download free 30-day trial

Dynamic PropertyDataSource

Some DataForm Editors such as PickerEditor and SegmentedEditor allow the app user to choose a value from a predefined list of values. In this case RadDataForm provides a mechanism to set a data source to these editors through the PropertyDataSourceProvider.

With R1 2020 release of Telerik UI for Xamarin RadDataForm provides means to refresh the data source of its Picker and Segmented editors. There are two ways to update the data source of a certain editor - either use an ObservableCollection, so that any changes are reflected to the underlying data source, or manually update it through the UpdatePropertyDataSource method. Both approaches are described in details in the next sections.

Dynamic PropertyDataSourceProvider updates are supported only in Manual CommitMode. For more details on the commit modes of RadDataForm check Validate and Commit topic.

Using ObservableCollection

Let's have the following source item for the DataForm:

public class Customer
{       
    [DisplayOptions(Header = "Name", Position = 0)]
    public string Name { get; set; }

    [DisplayOptions(Header = "Email", Position = 1)]
    public string Email { get; set; }

    [DisplayOptions(Header = "Country", Position = 2)]
    public string Country { get; set; }

    [DisplayOptions(Header = "City", Position = 3)]
    public string City { get; set; }
}

For the Country and City properties you can use PickerEditors in order to provide a list the user can choose from. The cities will depend on the chosen Country, meaning that you would need to refresh the City PickerEditor every time the selected Country is changed.

Let's continue with the implementation - add the DataForm definition:

<telerikInput:RadDataForm x:Name="dataForm" 
                          CommitMode="Manual"
                          EditorValueChanged="DataForm_EditorValueChanged" />

Configure the DataForm Editors and set PropertyDataSourceProvider:

dataForm.Source = new Customer();

dataForm.RegisterEditor(nameof(Customer.Country), EditorType.PickerEditor);
dataForm.RegisterEditor(nameof(Customer.City), EditorType.PickerEditor);

this.locationProvider = new LocationProvider();
this.locationProvider.Countries = new ObservableCollection<string>()
{ "Germany", "Argentina", "USA"};
this.UpdateCities(locationProvider.Countries[0]);

dataForm.PropertyDataSourceProvider = locationProvider;

Next, create the LocationProvider class which inherits from PropertyDataSourceProvider and defines two ObservableCollections that should hold the Countries and Cities values:

public class LocationProvider : PropertyDataSourceProvider
{
    public ObservableCollection<string> Cities = new ObservableCollection<string>();
    public ObservableCollection<string> Countries = new ObservableCollection<string>();
    public override IList GetSourceForKey(object key)
    {
        string keyString = key as string;

        if (keyString == nameof(Customer.Country))
        {
            return this.Countries;
        }
        else if (keyString == nameof(Customer.City))
        {
            return this.Cities;
        }
        else
        {
            return base.GetSourceForKey(key);
        }
    }
}

Lastly, add the EditorValueChanged event handler and in it update the City PickerEditor's Source depending on the selected Country:

private void DataForm_EditorValueChanged(object sender, Telerik.XamarinForms.Input.DataForm.EditorValueChangedEventArgs e)
{
    if (e.PropertyName == nameof(Customer.Country))
    {
       this.UpdateCities((string)e.NewValue);
    }
}

private void UpdateCities(string country)
{
    this.locationProvider.Cities.Clear();

    if (country == "Germany")
    {
        this.locationProvider.Cities.Add("Berlin");
        this.locationProvider.Cities.Add("Frankfurt am Main");
        this.locationProvider.Cities.Add("Hamburg");
    }
    else if (country == "Argentina")
    {
        this.locationProvider.Cities.Add("Buenos Aires");
        this.locationProvider.Cities.Add("Cordoba");
    }
    else
    {
        this.locationProvider.Cities.Add("Miami");
        this.locationProvider.Cities.Add("New York");
        this.locationProvider.Cities.Add("Los Angeles");                
    }
}

Using UpdatePropertyDataSource method

Through the UpdatePropertyDataSource method of the DataForm you can manually refresh the editor DataSource. The method received one argument - the name of the property corresponding to the editor.

Let's have the same scenario as in the first section with dependent Country-City Picker editors. Here is the DataForm source class:

public class Customer
{
    [DisplayOptions(Header = "Name", Position = 0)]
    public string Name { get; set; }

    [DisplayOptions(Header = "Email", Position = 1)]
    public string Email { get; set; }

    [DisplayOptions(Header = "Country", Position = 2)]
    public string Country { get; set; }

    [DisplayOptions(Header = "City", Position = 3)]
    public string City { get; set; }
}

And the DataForm definition:

<telerikInput:RadDataForm x:Name="dataForm" 
                          CommitMode="Manual"
                          EditorValueChanged="DataForm_EditorValueChanged" />

Next, setup the DataForm editors and define PropertyDataSourceProvider:

dataForm.Source = new Customer();

dataForm.RegisterEditor(nameof(Customer.Country), EditorType.PickerEditor);
dataForm.RegisterEditor(nameof(Customer.City), EditorType.PickerEditor);

this.locationProvider = new LocationProvider();
this.locationProvider.Countries = new List<string>() { "Germany", "Argentina", "USA" };
this.UpdateCities(locationProvider.Countries[0]);

dataForm.PropertyDataSourceProvider = locationProvider;            

Here is the LocationProvider class definition - note that Countries and Cities are defined as Lists:

public class LocationProvider : PropertyDataSourceProvider
{
    public List<string> Cities = new List<string>();
    public List<string> Countries;

    public override IList GetSourceForKey(object key)
    {
        string keyString = key as string;

        if (keyString == nameof(Customer.Country))
        {
            return this.Countries;
        }
        else if (keyString == nameof(Customer.City))
        {
            return this.Cities;
        }
        else
        {
            return base.GetSourceForKey(key);
        }
    }
}

Lastly, add the EditorValueChanged event handler and in it call the UpdatePropertyDataSource method to force the update of the City PickerEditor data source:

private void DataForm_EditorValueChanged(object sender, Telerik.XamarinForms.Input.DataForm.EditorValueChangedEventArgs e)
{
    if (e.PropertyName == nameof(Customer.Country))
    {
        this.UpdateCities((string)e.NewValue);
        dataForm.UpdatePropertyDataSource(nameof(Customer.City));
    }
}

private void UpdateCities(string country)
{
    this.locationProvider.Cities = new List<string>();

    if (country == "Germany")
    {
        this.locationProvider.Cities.Add("Berlin");
        this.locationProvider.Cities.Add("Frankfurt am Main");
        this.locationProvider.Cities.Add("Hamburg");
    }
    else if (country == "Argentina")
    {
        this.locationProvider.Cities.Add("Buenos Aires");
        this.locationProvider.Cities.Add("Cordoba");
    }
    else
    {
        this.locationProvider.Cities.Add("Miami");
        this.locationProvider.Cities.Add("New York");
        this.locationProvider.Cities.Add("Los Angeles");
    }
}

See Also

In this article