Windows icon indicating copy to clipboard operation
Windows copied to clipboard

New method to add token to RichSuggestBox

Open Marv51 opened this issue 5 months ago • 2 comments

Describe the bug

As mentioned on Discord, I would really love a new method on RichSuggestBox that allows the programmatic insertion of a new token.

The use-case for this is something like a toolbar that offers ways to insert tokens. Currently you need to type the prefix, and then use the provided suggestions.

I think it is quite a common case that you want to offer suggestions outside of the provided popup. In the sample people get suggested to at-mention when the user types @. But imagine if I want to have a custom menu that enables the user to at-mention the last couple of people they interacted with. This new method would make that quite easy to implement.

Steps to reproduce

Currently I create the token in a manual way that relies a bit too much on the inner workings of RichSuggestBox:

    private void AddToken(string displayText, object? tokenData)
    {
        var guid = Guid.NewGuid();
        if (mySuggestBox.TextDocument is not null)
        {
            mySuggestBox.AddTokens([new(guid, $"({displayText})") { Item = tokenData }]);

            mySuggestBox.TextDocument.Selection.SetText(Microsoft.UI.Text.TextSetOptions.Unhide, $"\u200B({displayText})\u200B");
            mySuggestBox.TextDocument.Selection.Link = $"\"{guid}\"";
            // I move the focus, but probably not needed in the toolkit:
            mySuggestBox.Focus(FocusState.Programmatic);
            mySuggestBox.TextDocument.Selection.MoveStart(Microsoft.UI.Text.TextRangeUnit.Story, 1);
            // note: the new Token is not available in `Tokens` here yet, some processing occurs.
            // It seems like the private method `ValidateTokensInDocument()` should be called here.
        }
    }

Expected behavior

The new method should add a token, allow me to set the displayed text and the associated data. The token should be inserted at the current text selection/position (In my experience the current position is at the end of the document if the user hasn't interacted with the content)

Screenshots

See the discord for a video of my current use-case

Code Platform

  • [ ] UWP
  • [x] WinAppSDK / WinUI 3
  • [ ] Web Assembly (WASM)
  • [ ] Android
  • [ ] iOS
  • [ ] MacOS
  • [ ] Linux / GTK

Windows Build Number

  • [ ] Windows 10 1809 (Build 17763)
  • [ ] Windows 10 1903 (Build 18362)
  • [ ] Windows 10 1909 (Build 18363)
  • [ ] Windows 10 2004 (Build 19041)
  • [ ] Windows 10 20H2 (Build 19042)
  • [ ] Windows 10 21H1 (Build 19043)
  • [ ] Windows 10 21H2 (Build 19044)
  • [ ] Windows 10 22H2 (Build 19045)
  • [x] Windows 11 21H2 (Build 22000)
  • [ ] Other (specify)

Other Windows Build number

No response

App minimum and target SDK version

  • [ ] Windows 10, version 1809 (Build 17763)
  • [ ] Windows 10, version 1903 (Build 18362)
  • [ ] Windows 10, version 1909 (Build 18363)
  • [ ] Windows 10, version 2004 (Build 19041)
  • [x] Windows 10, version 2104 (Build 20348)
  • [x] Windows 11, version 22H2 (Build 22000)
  • [ ] Other (specify)

Other SDK version

No response

Visual Studio Version

2022

Visual Studio Build Number

latest (17.14.9)

Device form factor

Desktop

Additional context

I find the tokenized richtextbox a very cool and powerful control, the use-case in the samples centered on suggestions are just the tip of the ice berg. I did not really look into this yet, but I believe a token must currently start with a punctuation character. But wouldn't it be neat if you could use an emoji? Imagine a paperclip with a document name to reference an attachment. 📎MyReport.pdf

Help us help you

No, I'm unable to contribute a solution.

Marv51 avatar Jul 23 '25 05:07 Marv51

The signature for this should be like:

public void InsertToken(ITextRange range, RichSuggestToken token)

It should do similar steps to the committing of a suggestion here:

https://github.com/CommunityToolkit/Windows/blob/5bc705f2f563549914327a04a61c4322b8fc7fef/components/RichSuggestBox/src/RichSuggestBox.Suggestion.cs#L77-L136

Not sure if that'd mean it'd have to be async, not as familiar with the inner workings here myself.

michael-hawker avatar Aug 28 '25 21:08 michael-hawker

SelectionChanging has the location information of the selection as well, though not SelectionChanged (which is exposed by the control), seems like a platform issue to investigate too.

https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.richeditboxselectionchangingeventargs?view=windows-app-sdk-1.7

Yeah, looks like SelectionChanged is defined: https://github.com/microsoft/microsoft-ui-xaml/blob/adae19431771d29b4c94d7a2bfd889e7d8c0fa4c/src/dxaml/xcp/tools/XCPTypesAutoGen/Modules/Controls/RichEditBox.cs#L290 - but I never see it raised searching in the https://github.com/microsoft/microsoft-ui-xaml/blob/adae19431771d29b4c94d7a2bfd889e7d8c0fa4c/src/dxaml/xcp/dxaml/lib/RichEditBox_Partial.cpp implementation.

Someone would need to do a quick repro and raise an issue, but seems like an oversight to not have the same information passed after selection made?

However folks can just grab an ITextRange from the selection of the document itself: https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.text.richedittextdocument.selection?view=windows-app-sdk-1.7 (which is either whatever the user has highlighted, or should be the cursor position if no selection from my understanding)

michael-hawker avatar Aug 28 '25 23:08 michael-hawker