Manage the Tokens Collection in .NET MAUI AutoComplete
Environment
Version | Product | Author |
---|---|---|
7.1.0 | Telerik UI for .NET MAUI AutoComplete | Dobrinka Yordanova |
Description
This article explains how to manage the tokens collection of the AutoComplete in MVVM scenario.
Solution
The Tokens
collection of the AutoComplete
is a read-only collection:
public ObservableCollection<object> Tokens { get; }
To add or remove tokens using an MVVM setup, create a custom behavior.
1. Create a TokensBehavior
class that inherits from Behavior<RadAutoComplete>
:
public class TokensBehavior : Behavior<RadAutoComplete>
{
public static readonly BindableProperty TokensProperty =
BindableProperty.Create(nameof(Tokens), typeof(ObservableCollection<object>), typeof(TokensBehavior), null, propertyChanged: OnTokensPropertyChanged);
private RadAutoComplete acv;
public ObservableCollection<object> Tokens
{
get
{
return (ObservableCollection<object>)this.GetValue(TokensProperty);
}
set
{
this.SetValue(TokensProperty, value);
}
}
protected override void OnAttachedTo(BindableObject bindable)
{
base.OnAttachedTo(bindable);
this.acv = (RadAutoComplete)bindable;
}
protected override void OnDetachingFrom(BindableObject bindable)
{
base.OnDetachingFrom(bindable);
}
private static void OnTokensPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var oldCollection = oldValue as INotifyCollectionChanged;
if (oldCollection != null)
{
oldCollection.CollectionChanged -= ((TokensBehavior)bindable).Tokens_CollectionChanged;
}
var collection = newValue as INotifyCollectionChanged;
if (collection != null)
{
((TokensBehavior)bindable).UpdateTransfer(newValue);
collection.CollectionChanged += ((TokensBehavior)bindable).Tokens_CollectionChanged;
}
}
private void UpdateTransfer(object tokens)
{
Transfer((ObservableCollection<object>)tokens, this.acv.Tokens);
this.acv.Tokens.CollectionChanged += Tokens_CollectionChanged1;
}
private void Tokens_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
this.UnsubscribeFromEvents();
Transfer(this.Tokens, this.acv.Tokens);
this.SubscribeToEvents();
}
private void Tokens_CollectionChanged1(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
this.UnsubscribeFromEvents();
Transfer(this.acv.Tokens, this.Tokens);
this.SubscribeToEvents();
}
}
private void SubscribeToEvents()
{
this.acv.Tokens.CollectionChanged += this.Tokens_CollectionChanged1;
if (this.Tokens != null)
{
this.Tokens.CollectionChanged += this.Tokens_CollectionChanged;
}
}
private void UnsubscribeFromEvents()
{
this.acv.Tokens.CollectionChanged -= this.Tokens_CollectionChanged1;
if (this.Tokens != null)
{
this.Tokens.CollectionChanged -= this.Tokens_CollectionChanged;
}
}
public static void Transfer(ObservableCollection<object> source, ObservableCollection<object> target)
{
if (source == null || target == null)
return;
target.Clear();
foreach (var o in source)
{
target.Add(o);
}
}
}
2. Set the behavior to the AutoComplete control:
<VerticalStackLayout>
<telerik:RadAutoComplete x:Name="autoCompleteView"
ItemsSource="{Binding Source}"
TextSearchPath="Name"
DisplayMode="Tokens">
<telerik:RadAutoComplete.Behaviors>
<local:TokensBehavior BindingContext="{Binding Source={x:Reference autoCompleteView}, Path=BindingContext}"
Tokens="{Binding SelectedTokens}"/>
</telerik:RadAutoComplete.Behaviors>
</telerik:RadAutoComplete>
<Button Text="Select Token" Command="{Binding SelectTokenCommand}"/>
<Button Text="Remove Token" Command="{Binding RemoveTokenCommand}"/>
</VerticalStackLayout>
3. Add the telerik
namespace:
xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
4. Add a sample model:
public class Customer
{
public Customer(string name, string email)
{
this.Name = name;
this.Email = email;
}
public string Name { get; set; }
public string Email { get; set; }
}
5. Add the ViewModel
:
public class ViewModel
{
public ObservableCollection<Customer> Source { get; set; }
public ViewModel()
{
this.Source = new ObservableCollection<Customer>()
{
new Customer("Freda Curtis", "fcurtis@mail.com"),
new Customer("Jeffery Francis", "jfrancis@mail.com"),
new Customer("Eva Lawson", "elawson@mail.com"),
new Customer("Emmett Santos", "esantos@mail.com"),
new Customer("Theresa Bryan", "tbryan@mail.com"),
new Customer("Jenny Fuller", "jfuller@mail.com"),
new Customer("Terrell Norris", "tnorris@mail.com"),
};
this.SelectTokenCommand = new Command(OnSelectTokenCommandExecuted);
this.RemoveTokenCommand = new Command(OnRemoveTokenCommandExecuted);
this.SelectedTokens = new ObservableCollection<object>();
}
public ICommand SelectTokenCommand { get; set; }
public ICommand RemoveTokenCommand { get; set; }
public ObservableCollection<object> SelectedTokens { get; set; }
private void OnSelectTokenCommandExecuted(object obj)
{
this.SelectedTokens.Add(this.Source[0]);
}
private void OnRemoveTokenCommandExecuted(object obj)
{
var item = this.SelectedTokens.FirstOrDefault();
if (item != null)
{
this.SelectedTokens.Remove(item);
}
}
}