Événement
Créer des applications intelligentes
17 mars, 21 h - 21 mars, 10 h
Rejoignez la série de rencontres pour créer des solutions IA évolutives basées sur des cas d’usage réels avec d’autres développeurs et experts.
S’inscrire maintenantCe navigateur n’est plus pris en charge.
Effectuez une mise à niveau vers Microsoft Edge pour tirer parti des dernières fonctionnalités, des mises à jour de sécurité et du support technique.
Le RichSuggestBox
est une combinaison de AutoSuggestBox et RichEditBox qui peuvent fournir des suggestions basées sur des préfixes personnalisables. Les suggestions sélectionnées sont incorporées et suivies dans le document en tant que jetons.
RichSuggestBox ressemble aux contrôles de texte couramment trouvés dans les applications sociales où vous tapez « @ » pour mentionner des personnes.
<!-- 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. -->
<Page x: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>
<DataTemplate x:Key="EmailTemplate">
<StackPanel Orientation="Horizontal">
<Border Width="20"
Height="20"
Background="{ThemeResource AccentFillColorDefaultBrush}"
CornerRadius="9999">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="10"
FontWeight="Semibold"
Foreground="White"
Text="{Binding Initials}" />
</Border>
<TextBlock Padding="8,0,0,0"
Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DataTemplate">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{Binding Icon}" />
<TextBlock Margin="8,0,0,0"
Text="{Binding Text}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="TokenTemplate">
<StackPanel Margin="0,4,0,12"
Orientation="Vertical">
<TextBlock>
<Run Text="Text:" />
<Run FontWeight="SemiBold"
Text="{Binding DisplayText}" />
</TextBlock>
<TextBlock>
<Run Text="Position:" />
<Run FontWeight="SemiBold"
Text="{Binding Position}" />
</TextBlock>
<TextBlock>
<Run Text="Id:" />
<Run FontWeight="SemiBold"
Text="{Binding Id}" />
</TextBlock>
</StackPanel>
</DataTemplate>
<local:SuggestionTemplateSelector x:Key="SuggestionTemplateSelector"
Data="{StaticResource DataTemplate}"
Person="{StaticResource EmailTemplate}" />
</Page.Resources>
<StackPanel MinWidth="400"
HorizontalAlignment="Center"
Spacing="24">
<controls:RichSuggestBox x:Name="SuggestingBox"
HorizontalAlignment="Stretch"
Header="RichSuggestBox that supports multiple prefixes (@ and #)"
ItemTemplateSelector="{StaticResource SuggestionTemplateSelector}"
Prefixes="@#"
SuggestionChosen="SuggestingBox_SuggestionChosen"
SuggestionRequested="SuggestingBox_SuggestionRequested" />
<ListView x:Name="TokenListView"
HorizontalAlignment="Stretch"
ItemTemplate="{StaticResource TokenTemplate}" />
</StackPanel>
</Page>
// 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 WINAPPSDK
using Microsoft.UI;
using Microsoft.UI.Text;
#else
using Windows.UI;
using Windows.UI.Text;
#endif
namespace RichSuggestBoxExperiment.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.")]
public sealed partial class RichSuggestBoxMultiplePrefixesSample : Page
{
private readonly 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" },
};
private readonly 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 },
};
public RichSuggestBoxMultiplePrefixesSample()
{
this.InitializeComponent();
TokenListView.ItemsSource = SuggestingBox.Tokens;
}
private void SuggestingBox_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;
}
}
private void SuggestingBox_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));
}
}
}
<controls:RichSuggestBox
PlaceholderText="Leave a comment"
ItemTemplate="{StaticResource SuggestionTemplate}"
Prefixes="@#" />
Lorsqu’une suggestion est sélectionnée, RichSuggestBox
attribue à l’élément sélectionné un guid unique Guid et un texte d’affichage (fourni par le développeur) pour constituer un jeton. Le texte d’affichage est ensuite rempli avec des espaces de largeur zéro (ZWSP) et inséré dans le document sous forme de lien hypertexte en utilisant l'identifiant comme adresse de lien. Ces liens hypertexte sont suivis et validés sur chaque modification de texte.
Le texte du jeton inséré dans le document a la disposition suivante : ZWSP – Caractère préfixe – Texte d’affichage – ZWSP.
Par exemple, un jeton avec « @ » comme préfixe et « John Doe » comme texte d’affichage est inséré comme suit :
"\u200b@John Doe\u200b"
Important
Le texte du jeton contient des espaces de largeur zéro, qui sont des caractères Unicode.
Note
Pour prendre en charge la fonction Annuler/Rétablir, RichSuggestBox
conserve tous les jetons dans une collection interne même lorsque le texte du jeton est supprimé du document. Ces jetons sont marqués comme inactifs et ne sont pas inclus dans la collection Tokens
. Utilisez la méthode ClearUndoRedoSuggestionHistory()
pour effacer les jetons inactifs ou la méthode Clear()
pour effacer tous les jetons.
L’exemple ci-dessous crée un RichSuggestBox
qui peut tokeniser à la fois les mentions (la requête commence par @
) et les hashtags (la requête commence par #
).
<controls:RichSuggestBox
PlaceholderText="Leave a comment"
ItemTemplate="{StaticResource SuggestionTemplate}"
SuggestionChosen="OnSuggestionChosen"
SuggestionRequested="OnSuggestionRequested"
Prefixes="@#" />
private void OnSuggestionChosen(RichSuggestBox sender, SuggestionChosenEventArgs args)
{
if (args.Prefix == "#")
{
// User selected a hashtag item
args.DisplayText = ((SampleHashtagDataType)args.SelectedItem).Text;
}
else
{
// User selected a mention item
args.DisplayText = ((SampleEmailDataType)args.SelectedItem).DisplayName;
}
}
private void OnSuggestionRequested(RichSuggestBox sender, SuggestionRequestedEventArgs args)
{
sender.ItemsSource = args.Prefix == "#"
? _hashtags.Where(x => x.Text.Contains(args.QueryText, StringComparison.OrdinalIgnoreCase))
: _emails.Where(x => x.DisplayName.Contains(args.QueryText, StringComparison.OrdinalIgnoreCase));
}
L’exemple ci-dessous crée un RichSuggestBox
qui n'autorise que la saisie de texte brut. Les seuls textes mis en forme dans le document sont des jetons.
<controls:RichSuggestBox
ClipboardCopyFormat="PlainText"
ClipboardPasteFormat="PlainText"
DisabledFormattingAccelerators="All" />
<!-- 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. -->
<Page x: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>
<DataTemplate x:Key="EmailTemplate">
<StackPanel Orientation="Horizontal">
<Border Width="20"
Height="20"
Background="{ThemeResource AccentFillColorDefaultBrush}"
CornerRadius="9999">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="10"
FontWeight="Semibold"
Foreground="White"
Text="{Binding Initials}" />
</Border>
<TextBlock Padding="8,0,0,0"
Text="{Binding DisplayName}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="TokenTemplate">
<StackPanel Margin="0,4,0,12"
Orientation="Vertical">
<TextBlock>
<Run Text="Text:" />
<Run FontWeight="SemiBold"
Text="{Binding DisplayText}" />
</TextBlock>
<TextBlock>
<Run Text="Position:" />
<Run FontWeight="SemiBold"
Text="{Binding Position}" />
</TextBlock>
<TextBlock>
<Run Text="Id:" />
<Run FontWeight="SemiBold"
Text="{Binding Id}" />
</TextBlock>
</StackPanel>
</DataTemplate>
<local:SuggestionTemplateSelector x:Key="SuggestionTemplateSelector"
Data="{StaticResource DataTemplate}"
Person="{StaticResource EmailTemplate}" />
<Flyout x:Key="TokenSelectedFlyout">
<ContentPresenter x:Name="FlyoutPresenter"
ContentTemplate="{StaticResource EmailTemplate}" />
</Flyout>
</Page.Resources>
<StackPanel MinWidth="400"
HorizontalAlignment="Center"
Spacing="24">
<controls:RichSuggestBox x: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" />
<ListView x:Name="TokenListView"
HorizontalAlignment="Stretch"
ItemTemplate="{StaticResource TokenTemplate}" />
</StackPanel>
</Page>
// 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 WINAPPSDK
using Microsoft.UI;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Text;
#else
using Windows.UI;
using Windows.System;
using Windows.UI.Text;
#endif
namespace RichSuggestBoxExperiment.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.")]
public sealed partial class RichSuggestBoxPlainTextSample : Page
{
private DispatcherQueue _dispatcherQueue;
private readonly 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" },
};
public RichSuggestBoxPlainTextSample()
{
this.InitializeComponent();
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
TokenListView.ItemsSource = SuggestingBox.Tokens;
}
private void SuggestingBox_SuggestionChosen(RichSuggestBox sender, SuggestionChosenEventArgs args)
{
args.DisplayText = ((SampleEmailDataType)args.SelectedItem!).DisplayName;
}
private void SuggestingBox_SuggestionRequested(RichSuggestBox sender, SuggestionRequestedEventArgs args)
{
sender.ItemsSource = this._emailSamples.Where(x => x.DisplayName.Contains(args.QueryText!, StringComparison.OrdinalIgnoreCase));
}
private void SuggestingBox_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,
});
});
}
}
}
Commentaires sur Windows Community Toolkit
Windows Community Toolkit est un projet open source. Sélectionnez un lien pour fournir des commentaires:
Événement
Créer des applications intelligentes
17 mars, 21 h - 21 mars, 10 h
Rejoignez la série de rencontres pour créer des solutions IA évolutives basées sur des cas d’usage réels avec d’autres développeurs et experts.
S’inscrire maintenantFormation
Parcours d’apprentissage
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
Documentation
RangeSelector - Community Toolkits for .NET
Le contrôle RangeSelector est un contrôle à double slider qui permet à l’utilisateur de sélectionner une sous-plage de valeurs à partir d’une plus grande plage de valeurs possibles. L’utilisateur peut faire glisser le curseur à partir de la gauche ou de la droite de la plage.
LayoutTransformControl - Community Toolkits for .NET
LayoutTransformControl est un contrôle qui prend en charge les transformations sur les FrameworkElement comme si elles étaient appliquées par LayoutTransform.
HeaderedContentControl - Community Toolkits for .NET
Le HeaderedContentControl permet d’afficher les éléments avec un en-tête spécifié.