How to create a custom Editor for List<string> - autocomplete

I'm been playing around with several examples of custom editors. I'd like to be able to use a backing field which is a List. However, as it stands when I create the dataform the field doesn't allow editing.

What I'm trying to do is have a field which allows autocomplete multiselectmode.token editor which also allows selecting/adding a new value which doesn't exist in the list yet. I do not want to use autogenerate dataform. Here's an outline of what I have setup currently. The OnCreateEditorView gets called, so I'm assuming it's trying to attach the custom editor to the field. However, the itemsource which is correctly set on the DataFormAutoCompleteItem when I debug into OnCreateEditorView doesn't seem to get set on the SfAutoComplete component. The app runs and the field is displayed, but you cannot click into it.
Any help would be appreciated.

XAML

LabelPosition="Top"
LayoutOptions="TextInputLayout"
ContainerType="Outlined"
ColumnCount="2"
AutoGenerateItems="False">
ColumnSpan="2"
BindingContext="{Binding Path=BindingContext, Source={x:Reference Name=viewModel}}"
ItemsSource="{Binding Passengers}"/>
DATAFORM BEHAVIOR
public class DataFormBehavior : Behavior
{
SfDataForm dataForm;
protected override void OnAttachedTo(SfDataForm bindable)
{
base.OnAttachedTo(bindable);
dataForm = bindable;
dataForm.RegisterEditor("PassengersEdit", new PassangerListEditor(dataForm));
}
}
VIEW MODEL
public class PaxViewModel : BaseViewModel
{
private FormEdit form;
public FormEdit Form
{
get => form;
set => SetProperty(ref form, value);
}
public ObservableCollection pax;
public ObservableCollection Passengers
{
get => pax;
set => SetProperty(ref pax, value);
}
public PaxViewModel()
{
pax = new ObservableCollection(){ "john", "keith" };
Form = new FormEdit();//dataobject
}
}
FORMEDIT
public class FormEdit: NotifyPropertyChangedBase
{
private List passengers = new List();
public List Passengers
{
get => passengers;
set=> SetProperty(ref passengers, value);
}
}
CUSTOMEDITOR
public class PassangerListEditor : DataFormAutoCompleteEditor
{
private SfDataForm sfDataForm;
private DataFormAutoCompleteItem item;
public PassangerListEditor(SfDataForm dataForm) : base(dataForm)
{
this.sfDataForm = dataForm;
}
protected override void OnInitializeView(DataFormItem dataFormItem, SfAutoComplete view)
{
view.MultiSelectMode = MultiSelectMode.Token;
view.TokensWrapMode = TokensWrapMode.Wrap;
view.Unfocused += View_Unfocused;
item = dataFormItem as DataFormAutoCompleteItem;
base.OnInitializeView(dataFormItem, view);
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
}
protected override SfAutoComplete OnCreateEditorView(DataFormItem dataFormItem)
{
var view = base.OnCreateEditorView(dataFormItem);
view.MultiSelectMode = MultiSelectMode.Token;
view.TokensWrapMode = TokensWrapMode.Wrap;
view.IsEnabled = true;
return view;
}
protected override void OnCommitValue(SfAutoComplete view)
{
(sfDataForm.DataObject as FlightEdit).Passengers = (List) view.SelectedValue;
}
protected override void OnUpdateValue(DataFormItem dataFormItem, SfAutoComplete view)
{
base.OnUpdateValue(dataFormItem, view);
}
private void View_Unfocused(object sender, FocusEventArgs e)
{
var autoComplete = sender as SfAutoComplete;
var text = autoComplete.Text;
if (string.IsNullOrEmpty(text))
return;
var selectedItem = autoComplete.SelectedItem;
//todo: add new to list here
}
protected override void OnUnWireEvents(SfAutoComplete view)
{
base.OnUnWireEvents(view);
view.Unfocused -= View_Unfocused;
}
}

6 Replies 1 reply marked as answer

SS SaiGanesh Sakthivel Syncfusion Team February 10, 2021 02:12 PM UTC

Hi Keith, 
 
Thank you for using Syncfusion support. 
 
#Regarding How to register the CustomAutoCompleteEditor to the DataForm 
We would like to inform you that you can achieve your requirement with the help of creating CustomAutoCompleteEditor by exacting from the DataFormAutoCompleteEditor and register to the dataform RegisterEditor property. Please refer to the following Code snippet for your reference. 
 
Code Snippet 
dataForm.RegisterEditor("AutoComplete", new CustomAutoCompleteEditor(dataForm));



<dataForm:SfDataForm x:Name="dataForm" DataObject="{Binding ContactsInfo}" LayoutOptions="TextInputLayout"   AutoGenerateItems="False">
 
    <dataForm:SfDataForm.Items> 
        <dataForm:DataFormItem Name="FirstName" Editor="Text" /> 
        <dataForm:DataFormItem Name="LastName" Editor="Text"/> 
        <dataForm:DataFormAutoCompleteItem Name="Country" BindingContext="{x:Reference Client}" Editor="AutoComplete" ItemsSource ="{Binding Addresses}"  /> 
    </dataForm:SfDataForm.Items> 
</dataForm:SfDataForm> 
 
Please refer to the tested sample in the following link for your reference. 
 
Please let us know if you have any concern. 
 
Regards, 
SaiGanesh Sakthivel 


Marked as answer

TR tracstarr February 10, 2021 02:47 PM UTC

I've taken a look at the sample. There is an issue with it. (Android). When I enter a new value for Country and cause unfocused to be called, it will correctly add the value to the source, but when calling updateeditor the screen (android) becomes gray and I must touch the screen to make it active again. At the same time, the Country value is not updated to what was just entered (if changing from a previously selected country) - it remains as the previously country until you select the new added one. 

Additionally, what I was hoping to have is, using your sample, ContactInfo.Country as a List<string> and allow multiple selection from the custom editor. 


TR tracstarr February 11, 2021 01:07 AM UTC

So after a lot of playing around with the sample I was finally able to get it to do most of what I want. I've attached my changes. What I'm still having issues with is that with the multiselect option, the last made selection doesn't update the bound model value until the control looses focus. This causes issues in my app when clicking on a save button. Is there a way to commit selected items right away?

Attachment: DataFormXamarin_1ee2b9ec.7z


TR tracstarr February 11, 2021 01:14 AM UTC

There are still some other use cases I've found not working. I can't add a new entry after selecting others. 


SS SaiGanesh Sakthivel Syncfusion Team February 12, 2021 03:39 AM UTC

Hi Keith, 
 
Thank you for the update. 
 
We have validating the reported query “custom Editor for List<string> - autocomplete” from our end. We are currently working on it and update you further details on February 15, 2021. We appreciate your patience until then. 
 
Regards, 
SaiGanesh Sakthivel 



SS SaiGanesh Sakthivel Syncfusion Team February 15, 2021 11:46 AM UTC

Hi Keith, 
 
Thank you for the patience. 
 
#Regarding custom Editor for List<string> - autocomplete 
We would like to inform you that you can achieve your requirement with help of completed event in SfAutoCompleteEditor. Inside the completed event, you can add the new text by clicking done button to add the new text in the collection. Please refer to the following code snippet for your reference. 
 
Code Snippet: 
protected override void OnInitializeView(DataFormItem dataFormItem, SfAutoComplete view) 
{ 
    base.OnInitializeView(dataFormItem, view); 
    autoComplete = view; 
    view.Completed += View_Completed; 
    autoCompleteItem = dataFormItem as DataFormAutoCompleteItem; 
    view.ShowSuggestionsOnFocus = true; 
    view.MultiSelectMode = MultiSelectMode.Token; 
    view.SelectionType = SelectionType.Default; 
    view.TokensWrapMode = TokensWrapMode.Wrap; 
    view.EnableAutoSize = true; 
}

private void View_Completed(object sender, System.EventArgs e)
 
{ 
    var text = autoComplete.Text; 
    if (string.IsNullOrEmpty(text)) 
        return; 
    var selectedItems = autoComplete.SelectedValue as List<string>; 
    var exists = (autoCompleteItem.ItemsSource as IList<string>).Contains(text); 
    if (selectedItems == null || !exists) 
    { 
        autoCompleteItem.ItemsSource.Add(text); 
        sfDataForm.UpdateEditor("Country"); 
        if (autoComplete.SelectedItem is ObservableCollection<object>) 
        { 
            (autoComplete.SelectedItem as ObservableCollection<object>).Add(text); 
        } 
    } 
} 
Please refer to the tested sample in the following link for your reference. 
 
Please let us know if you have any concern. 
 
Regards, 
SaiGanesh Sakthivel

Loader.
Up arrow icon