Jest RichSuggestBox to kombinacja autosuggestBox i RichEditBox , która może udostępniać sugestie na podstawie dostosowywalnych prefiksów. Wybrane sugestie są osadzone i śledzone w dokumencie jako tokeny.
Element RichSuggestBox przypomina kontrolki tekstu często występujące w aplikacjach społecznościowych, w których wpiszesz "@", aby wspomnieć o osobach.
XAML
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. --><Pagex:Class="RichSuggestBoxExperiment.Samples.RichSuggestBoxMultiplePrefixesSample"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="using:CommunityToolkit.WinUI.Controls"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="using:RichSuggestBoxExperiment.Samples"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"><Page.Resources><DataTemplatex:Key="EmailTemplate"><StackPanelOrientation="Horizontal"><BorderWidth="20"Height="20"Background="{ThemeResource AccentFillColorDefaultBrush}"CornerRadius="9999"><TextBlockHorizontalAlignment="Center"VerticalAlignment="Center"FontSize="10"FontWeight="Semibold"Foreground="White"Text="{Binding Initials}" /></Border><TextBlockPadding="8,0,0,0"Text="{Binding DisplayName}" /></StackPanel></DataTemplate><DataTemplatex:Key="DataTemplate"><StackPanelOrientation="Horizontal"><SymbolIconSymbol="{Binding Icon}" /><TextBlockMargin="8,0,0,0"Text="{Binding Text}" /></StackPanel></DataTemplate><DataTemplatex:Key="TokenTemplate"><StackPanelMargin="0,4,0,12"Orientation="Vertical"><TextBlock><RunText="Text:" /><RunFontWeight="SemiBold"Text="{Binding DisplayText}" /></TextBlock><TextBlock><RunText="Position:" /><RunFontWeight="SemiBold"Text="{Binding Position}" /></TextBlock><TextBlock><RunText="Id:" /><RunFontWeight="SemiBold"Text="{Binding Id}" /></TextBlock></StackPanel></DataTemplate><local:SuggestionTemplateSelectorx:Key="SuggestionTemplateSelector"Data="{StaticResource DataTemplate}"Person="{StaticResource EmailTemplate}" /></Page.Resources><StackPanelMinWidth="400"HorizontalAlignment="Center"Spacing="24"><controls:RichSuggestBoxx:Name="SuggestingBox"HorizontalAlignment="Stretch"Header="RichSuggestBox that supports multiple prefixes (@ and #)"ItemTemplateSelector="{StaticResource SuggestionTemplateSelector}"Prefixes="@#"SuggestionChosen="SuggestingBox_SuggestionChosen"SuggestionRequested="SuggestingBox_SuggestionRequested" /><ListViewx:Name="TokenListView"HorizontalAlignment="Stretch"ItemTemplate="{StaticResource TokenTemplate}" /></StackPanel></Page>
C#
// Licensed to the .NET Foundation under one or more agreements.// The .NET Foundation licenses this file to you under the MIT license.// See the LICENSE file in the project root for more information.using CommunityToolkit.WinUI.Controls;
#if WINAPPSDKusing Microsoft.UI;
using Microsoft.UI.Text;
#elseusing Windows.UI;
using Windows.UI.Text;
#endifnamespaceRichSuggestBoxExperiment.Samples;
[ToolkitSample(id: nameof(RichSuggestBoxMultiplePrefixesSample), "RichSuggestBox with multiple prefixes", description: $"A sample for showing how to create and use a {nameof(RichSuggestBox)} with multiple prefixes.")]
publicsealedpartialclassRichSuggestBoxMultiplePrefixesSample : Page
{
privatereadonly List<SampleEmailDataType> _emailSamples = new List<SampleEmailDataType>()
{
new SampleEmailDataType() { FirstName = "Marcus", FamilyName = "Perryman" },
new SampleEmailDataType() { FirstName = "Michael", FamilyName = "Hawker" },
new SampleEmailDataType() { FirstName = "Matt", FamilyName = "Lacey" },
new SampleEmailDataType() { FirstName = "Alexandre", FamilyName = "Chohfi" },
new SampleEmailDataType() { FirstName = "Filip", FamilyName = "Wallberg" },
new SampleEmailDataType() { FirstName = "Shane", FamilyName = "Weaver" },
new SampleEmailDataType() { FirstName = "Vincent", FamilyName = "Gromfeld" },
new SampleEmailDataType() { FirstName = "Sergio", FamilyName = "Pedri" },
new SampleEmailDataType() { FirstName = "Alex", FamilyName = "Wilber" },
new SampleEmailDataType() { FirstName = "Allan", FamilyName = "Deyoung" },
new SampleEmailDataType() { FirstName = "Adele", FamilyName = "Vance" },
new SampleEmailDataType() { FirstName = "Grady", FamilyName = "Archie" },
new SampleEmailDataType() { FirstName = "Megan", FamilyName = "Bowen" },
new SampleEmailDataType() { FirstName = "Ben", FamilyName = "Walters" },
new SampleEmailDataType() { FirstName = "Debra", FamilyName = "Berger" },
new SampleEmailDataType() { FirstName = "Emily", FamilyName = "Braun" },
new SampleEmailDataType() { FirstName = "Christine", FamilyName = "Cline" },
new SampleEmailDataType() { FirstName = "Enrico", FamilyName = "Catteneo" },
new SampleEmailDataType() { FirstName = "Davit", FamilyName = "Badalyan" },
new SampleEmailDataType() { FirstName = "Diego", FamilyName = "Siciliani" },
new SampleEmailDataType() { FirstName = "Raul", FamilyName = "Razo" },
new SampleEmailDataType() { FirstName = "Miriam", FamilyName = "Graham" },
new SampleEmailDataType() { FirstName = "Lynne", FamilyName = "Robbins" },
new SampleEmailDataType() { FirstName = "Lydia", FamilyName = "Holloway" },
new SampleEmailDataType() { FirstName = "Nestor", FamilyName = "Wilke" },
new SampleEmailDataType() { FirstName = "Patti", FamilyName = "Fernandez" },
new SampleEmailDataType() { FirstName = "Pradeep", FamilyName = "Gupta" },
new SampleEmailDataType() { FirstName = "Joni", FamilyName = "Sherman" },
new SampleEmailDataType() { FirstName = "Isaiah", FamilyName = "Langer" },
new SampleEmailDataType() { FirstName = "Irvin", FamilyName = "Sayers" },
new SampleEmailDataType() { FirstName = "Tung", FamilyName = "Huynh" },
};
privatereadonly List<SampleDataType> _samples = new List<SampleDataType>()
{
new SampleDataType() { Text = "Account", Icon = Symbol.Account },
new SampleDataType() { Text = "Add Friend", Icon = Symbol.AddFriend },
new SampleDataType() { Text = "Attach", Icon = Symbol.Attach },
new SampleDataType() { Text = "Attach Camera", Icon = Symbol.AttachCamera },
new SampleDataType() { Text = "Audio", Icon = Symbol.Audio },
new SampleDataType() { Text = "Block Contact", Icon = Symbol.BlockContact },
new SampleDataType() { Text = "Calculator", Icon = Symbol.Calculator },
new SampleDataType() { Text = "Calendar", Icon = Symbol.Calendar },
new SampleDataType() { Text = "Camera", Icon = Symbol.Camera },
new SampleDataType() { Text = "Contact", Icon = Symbol.Contact },
new SampleDataType() { Text = "Favorite", Icon = Symbol.Favorite },
new SampleDataType() { Text = "Link", Icon = Symbol.Link },
new SampleDataType() { Text = "Mail", Icon = Symbol.Mail },
new SampleDataType() { Text = "Map", Icon = Symbol.Map },
new SampleDataType() { Text = "Phone", Icon = Symbol.Phone },
new SampleDataType() { Text = "Pin", Icon = Symbol.Pin },
new SampleDataType() { Text = "Rotate", Icon = Symbol.Rotate },
new SampleDataType() { Text = "Rotate Camera", Icon = Symbol.RotateCamera },
new SampleDataType() { Text = "Send", Icon = Symbol.Send },
new SampleDataType() { Text = "Tags", Icon = Symbol.Tag },
new SampleDataType() { Text = "UnFavorite", Icon = Symbol.UnFavorite },
new SampleDataType() { Text = "UnPin", Icon = Symbol.UnPin },
new SampleDataType() { Text = "Zoom", Icon = Symbol.Zoom },
new SampleDataType() { Text = "ZoomIn", Icon = Symbol.ZoomIn },
new SampleDataType() { Text = "ZoomOut", Icon = Symbol.ZoomOut },
};
publicRichSuggestBoxMultiplePrefixesSample()
{
this.InitializeComponent();
TokenListView.ItemsSource = SuggestingBox.Tokens;
}
privatevoidSuggestingBox_SuggestionChosen(RichSuggestBox sender, SuggestionChosenEventArgs args)
{
if (args.Prefix == "#")
{
args.Format!.BackgroundColor = Colors.LightSlateGray;
args.Format.ForegroundColor = Colors.White;
args.Format.Bold = FormatEffect.On;
args.DisplayText = ((SampleDataType)args.SelectedItem!).Text;
}
else
{
args.DisplayText = ((SampleEmailDataType)args.SelectedItem!).DisplayName;
}
}
privatevoidSuggestingBox_SuggestionRequested(RichSuggestBox sender, SuggestionRequestedEventArgs args)
{
if (args.Prefix == "#")
{
sender.ItemsSource = this._samples.Where(x => x.Text.Contains(args.QueryText!, StringComparison.OrdinalIgnoreCase));
}
else
{
sender.ItemsSource = this._emailSamples.Where(x => x.DisplayName.Contains(args.QueryText!, StringComparison.OrdinalIgnoreCase));
}
}
}
Składnia
XAML
<controls:RichSuggestBoxPlaceholderText="Leave a comment"ItemTemplate="{StaticResource SuggestionTemplate}"Prefixes="@#" />
Uwagi
Po wybraniu RichSuggestBox sugestii przypisuje wybrany element unikatowy identyfikator GUID i tekst wyświetlany (dostarczony przez dewelopera), aby utworzyć token. Tekst wyświetlany jest następnie dopełniany spacjami o zerowej szerokości(ZWSP) i wstawiany do dokumentu jako hiperlink przy użyciu identyfikatora jako adresu łącza. Te hiperlinki są śledzone i weryfikowane przy każdej zmianie tekstu.
Tekst tokenu wstawiony do dokumentu ma następujący układ: ZWSP — znak prefiksu — Wyświetlanie tekstu — ZWSP.
Na przykład token "@" jako prefiks i "John Doe" jako tekst wyświetlany jest wstawiany jako:
cs
"\u200b@John Doe\u200b"
Ważne
Tekst tokenu zawiera spację zero widths, które są znakami Unicode.
Uwaga
Aby obsługiwać funkcję Cofnij/Powtórz, przechowuje wszystkie tokeny w kolekcji wewnętrznej nawet wtedy, RichSuggestBox gdy tekst tokenu zostanie usunięty z dokumentu. Token ten jest oznaczony jako nieaktywny i nie jest uwzględniony w kolekcji Tokens . Użyj ClearUndoRedoSuggestionHistory() metody , aby wyczyścić nieaktywne tokeny lub Clear() metodę, aby wyczyścić wszystkie tokeny.
Przykłady
Obsługa wielu typów tokenów
Poniższy przykład tworzy obiekt RichSuggestBox , który może tokenizować obie wzmianki (zapytanie rozpoczyna się od @) i hasztagi (zapytanie rozpoczyna się od #).
XAML
<controls:RichSuggestBoxPlaceholderText="Leave a comment"ItemTemplate="{StaticResource SuggestionTemplate}"SuggestionChosen="OnSuggestionChosen"SuggestionRequested="OnSuggestionRequested"Prefixes="@#" />
Poniższy przykład tworzy obiekt RichSuggestBox , który umożliwia tylko użytkownikom wprowadzanie zwykłego tekstu. Jedynymi sformatowanymi tekstami w dokumencie są tokeny.
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. --><Pagex:Class="RichSuggestBoxExperiment.Samples.RichSuggestBoxPlainTextSample"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="using:CommunityToolkit.WinUI.Controls"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="using:RichSuggestBoxExperiment.Samples"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"><Page.Resources><DataTemplatex:Key="EmailTemplate"><StackPanelOrientation="Horizontal"><BorderWidth="20"Height="20"Background="{ThemeResource AccentFillColorDefaultBrush}"CornerRadius="9999"><TextBlockHorizontalAlignment="Center"VerticalAlignment="Center"FontSize="10"FontWeight="Semibold"Foreground="White"Text="{Binding Initials}" /></Border><TextBlockPadding="8,0,0,0"Text="{Binding DisplayName}" /></StackPanel></DataTemplate><DataTemplatex:Key="TokenTemplate"><StackPanelMargin="0,4,0,12"Orientation="Vertical"><TextBlock><RunText="Text:" /><RunFontWeight="SemiBold"Text="{Binding DisplayText}" /></TextBlock><TextBlock><RunText="Position:" /><RunFontWeight="SemiBold"Text="{Binding Position}" /></TextBlock><TextBlock><RunText="Id:" /><RunFontWeight="SemiBold"Text="{Binding Id}" /></TextBlock></StackPanel></DataTemplate><local:SuggestionTemplateSelectorx:Key="SuggestionTemplateSelector"Data="{StaticResource DataTemplate}"Person="{StaticResource EmailTemplate}" /><Flyoutx:Key="TokenSelectedFlyout"><ContentPresenterx:Name="FlyoutPresenter"ContentTemplate="{StaticResource EmailTemplate}" /></Flyout></Page.Resources><StackPanelMinWidth="400"HorizontalAlignment="Center"Spacing="24"><controls:RichSuggestBoxx:Name="SuggestingBox"MaxHeight="400"HorizontalAlignment="Stretch"ClipboardCopyFormat="PlainText"ClipboardPasteFormat="PlainText"DisabledFormattingAccelerators="All"FlyoutBase.AttachedFlyout="{StaticResource TokenSelectedFlyout}"Header="Plain text RichSuggestBox with on token pointer over flyout"ItemTemplate="{StaticResource EmailTemplate}"Prefixes="@"SuggestionChosen="SuggestingBox_SuggestionChosen"SuggestionRequested="SuggestingBox_SuggestionRequested"TokenPointerOver="SuggestingBox_TokenPointerOver" /><ListViewx:Name="TokenListView"HorizontalAlignment="Stretch"ItemTemplate="{StaticResource TokenTemplate}" /></StackPanel></Page>
C#
// Licensed to the .NET Foundation under one or more agreements.// The .NET Foundation licenses this file to you under the MIT license.// See the LICENSE file in the project root for more information.using CommunityToolkit.WinUI.Controls;
#if WINAPPSDKusing Microsoft.UI;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Text;
#elseusing Windows.UI;
using Windows.System;
using Windows.UI.Text;
#endifnamespaceRichSuggestBoxExperiment.Samples;
[ToolkitSample(id: nameof(RichSuggestBoxPlainTextSample), "RichSuggestBox with plain text", description: $"A sample for showing how to create and use a {nameof(RichSuggestBox)} with plain text.")]
publicsealedpartialclassRichSuggestBoxPlainTextSample : Page
{
private DispatcherQueue _dispatcherQueue;
privatereadonly List<SampleEmailDataType> _emailSamples = new List<SampleEmailDataType>()
{
new SampleEmailDataType() { FirstName = "Marcus", FamilyName = "Perryman" },
new SampleEmailDataType() { FirstName = "Michael", FamilyName = "Hawker" },
new SampleEmailDataType() { FirstName = "Matt", FamilyName = "Lacey" },
new SampleEmailDataType() { FirstName = "Alexandre", FamilyName = "Chohfi" },
new SampleEmailDataType() { FirstName = "Filip", FamilyName = "Wallberg" },
new SampleEmailDataType() { FirstName = "Shane", FamilyName = "Weaver" },
new SampleEmailDataType() { FirstName = "Vincent", FamilyName = "Gromfeld" },
new SampleEmailDataType() { FirstName = "Sergio", FamilyName = "Pedri" },
new SampleEmailDataType() { FirstName = "Alex", FamilyName = "Wilber" },
new SampleEmailDataType() { FirstName = "Allan", FamilyName = "Deyoung" },
new SampleEmailDataType() { FirstName = "Adele", FamilyName = "Vance" },
new SampleEmailDataType() { FirstName = "Grady", FamilyName = "Archie" },
new SampleEmailDataType() { FirstName = "Megan", FamilyName = "Bowen" },
new SampleEmailDataType() { FirstName = "Ben", FamilyName = "Walters" },
new SampleEmailDataType() { FirstName = "Debra", FamilyName = "Berger" },
new SampleEmailDataType() { FirstName = "Emily", FamilyName = "Braun" },
new SampleEmailDataType() { FirstName = "Christine", FamilyName = "Cline" },
new SampleEmailDataType() { FirstName = "Enrico", FamilyName = "Catteneo" },
new SampleEmailDataType() { FirstName = "Davit", FamilyName = "Badalyan" },
new SampleEmailDataType() { FirstName = "Diego", FamilyName = "Siciliani" },
new SampleEmailDataType() { FirstName = "Raul", FamilyName = "Razo" },
new SampleEmailDataType() { FirstName = "Miriam", FamilyName = "Graham" },
new SampleEmailDataType() { FirstName = "Lynne", FamilyName = "Robbins" },
new SampleEmailDataType() { FirstName = "Lydia", FamilyName = "Holloway" },
new SampleEmailDataType() { FirstName = "Nestor", FamilyName = "Wilke" },
new SampleEmailDataType() { FirstName = "Patti", FamilyName = "Fernandez" },
new SampleEmailDataType() { FirstName = "Pradeep", FamilyName = "Gupta" },
new SampleEmailDataType() { FirstName = "Joni", FamilyName = "Sherman" },
new SampleEmailDataType() { FirstName = "Isaiah", FamilyName = "Langer" },
new SampleEmailDataType() { FirstName = "Irvin", FamilyName = "Sayers" },
new SampleEmailDataType() { FirstName = "Tung", FamilyName = "Huynh" },
};
publicRichSuggestBoxPlainTextSample()
{
this.InitializeComponent();
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
TokenListView.ItemsSource = SuggestingBox.Tokens;
}
privatevoidSuggestingBox_SuggestionChosen(RichSuggestBox sender, SuggestionChosenEventArgs args)
{
args.DisplayText = ((SampleEmailDataType)args.SelectedItem!).DisplayName;
}
privatevoidSuggestingBox_SuggestionRequested(RichSuggestBox sender, SuggestionRequestedEventArgs args)
{
sender.ItemsSource = this._emailSamples.Where(x => x.DisplayName.Contains(args.QueryText!, StringComparison.OrdinalIgnoreCase));
}
privatevoidSuggestingBox_TokenPointerOver(RichSuggestBox sender, RichSuggestTokenPointerOverEventArgs args)
{
var flyout = (Flyout)FlyoutBase.GetAttachedFlyout(sender);
var pointerPosition = args.CurrentPoint!.Position;
if (flyout?.Content is ContentPresenter cp && sender.TextDocument!.Selection.Type != SelectionType.Normal &&
(!flyout.IsOpen || cp.Content != args.Token!.Item))
{
this._dispatcherQueue.TryEnqueue(() =>
{
cp.Content = args.Token!.Item;
flyout.ShowAt(sender, new FlyoutShowOptions
{
Position = pointerPosition,
ExclusionRect = sender.GetRectFromRange(args.Range!),
ShowMode = FlyoutShowMode.TransientWithDismissOnPointerMoveAway,
});
});
}
}
}
Współpracuj z nami w serwisie GitHub
Źródło tej zawartości można znaleźć w witrynie GitHub, gdzie można również tworzyć i przeglądać problemy i żądania ściągnięcia. Więcej informacji znajdziesz w naszym przewodniku dla współtwórców.
Opinia o produkcie Windows Community Toolkit
Windows Community Toolkit to projekt typu open source. Wybierz link, aby przekazać opinię:
Dołącz do serii meetup, aby tworzyć skalowalne rozwiązania sztucznej inteligencji oparte na rzeczywistych przypadkach użycia z innymi deweloperami i ekspertami.