CommunityToolkit / CommunityToolkit/Windows
[Feature] TokenizingTextBox - Make TokenItemAdding event to be invoked even if the adding object is not a string to allow pre-check and cancellation
- Dominant language
- C#
- Stars
- 1.1k
- Forks
- 166
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the problem
Currently, [`TokenizingTextBox`](https://github.com/CommunityToolkit/Windows/blob/main/components/TokenizingTextBox/src/TokenizingTextBox.cs) does not fire [`TokenItemAdding`](https://github.com/CommunityToolkit/Windows/blob/5fd59df3d2e65cc2d38e62386b73a692105e2f30/components/TokenizingTextBox/src/TokenizingTextBox.Events.cs#L30) event when the `data` parameter in [`AddTokenAsync(object data)`](https://github.com/CommunityToolkit/Windows/blob/5fd59df3d2e65cc2d38e62386b73a692105e2f30/components/TokenizingTextBox/src/TokenizingTextBox.cs#L494) is not a `string`.
So when the user selects the already added item from `SuggestedItemsSource`, only `QuerySubmitted` event is invoked and I cannot prevent the duplicate item adding.
Thus, allowing `TokenItemAdding` to be invoked even if the `data` parameter is not a `string` would allow me to prevent duplicate items adding by checking the adding object and cancelling the event.
### Describe the solution
Modify [`AddTokenAsync(object data)`](https://github.com/CommunityToolkit/Windows/blob/5fd59df3d2e65cc2d38e62386b73a692105e2f30/components/TokenizingTextBox/src/TokenizingTextBox.cs#L494)
```
if (TokenItemAdding != null)
{
TokenItemAddingEventArgs tiaea;
if (data is string str)
{
tiaea = new TokenItemAddingEventArgs(str);
}
else
{
tiaea = new TokenItemAddingEventArgs(null) { Item = data };
}
await TokenItemAdding.InvokeAsync(this, tiaea);
...
}
```
### Alternatives
1. Create new `TokenizingTextBoxQuerySubmittedEventArgs` class and either remove `sealed` from `AutoSuggestBoxQuerySubmittedEventArgs` and derive from it like this:
```
public class TokenizingTextBoxQuerySubmittedEventArgs : AutoSuggestBoxQuerySubmittedEventArgs
{
public bool Cancel { get; set; }
}
```
Or just create a similar class with additional `Cancel` property:
```
public class TokenizingTextBoxQuerySubmittedEventArgs
{
public object ChosenSuggestion { get; }
public string QueryText { get; }
public bool Cancel { get; set; } = false;
}
```
2. Create a new `TokenizingTextBoxQuerySubmitted` event in [`TokenizingTextBox.Events.cs`](https://github.com/CommunityToolkit/Windows/blob/5fd59df3d2e65cc2d38e62386b73a692105e2f30/components/TokenizingTextBox/src/TokenizingTextBox.Events.cs)
```
public event TypedEventHandler TokenizingTextBoxQuerySubmitted;
```
3. Modify [`RaiseQuerySubmitted`](https://github.com/kaismic/Windows/blob/ee32a0a854f108afaabb9bbc07b58f665ef95161/components/TokenizingTextBox/src/TokenizingTextBox.cs#L243C1-L246C6)
```
internal void RaiseQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs
args, TokenizingTextBoxQuerySubmittedEventArgs args)
{
TokenizingTextBoxQuerySubmitted?.Invoke(sender, ttbArgs);
QuerySubmitted?.Invoke(sender, args);
}
```
4. Modify [`AutoSuggestBox_QuerySubmitted`](https://github.com/kaismic/Windows/blob/5fd59df3d2e65cc2d38e62386b73a692105e2f30/components/TokenizingTextBox/src/TokenizingTextBoxItem.AutoSuggestBox.cs#L138)
```
private async void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
var ttbArgs = new TokenizingTextBoxQuerySubmittedEventArgs()
{
ChosenSuggestion = args.ChosenSuggestion,
QueryText = args.QueryText
};
Owner.RaiseQuerySubmitted(sender, args, ttbArgs);
if (ttbArgs.Cancel)
{
return;
}
object? chosenItem = null;
....
}
```
### Additional info
_No response_
### Help us help you
None
Contributor guide
Assessment
This issue has not been assessed yet.