Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Demandez maintenant à l’assistant de créer la page. Nommez les contrôles WinUI souhaités afin qu’il ne remplace pas un contrôle d’une autre infrastructure d’interface utilisateur.
Demander le code XAML
Ignorez cette invite :
Create MainPage.xaml for TaskTally.
- Use a TextBox with a visible Header and an Add task Button.
- Use ListView for the task collection. Don't wrap it in ScrollViewer.
- In each row, use a CheckBox, task title, and delete Button.
- Use InfoBar for save and error status.
- Use x:Bind and specify Mode for every binding that changes.
- For TextBox.Text, use Mode=TwoWay and
UpdateSourceTrigger=PropertyChanged.
- Add accessible names and tooltips for icon-only commands.
- Add an empty state.
- At widths below 640 effective pixels, move the Add task button
below the TextBox and stretch it.
- Use theme resources instead of hard-coded colors.
- Build and fix all XAML compiler and analyzer warnings.
Inspectez ces détails dans le code XAML généré.
Entrée de données
<TextBox
x:Name="NewTaskTextBox"
Header="New task"
PlaceholderText="For example, review the generated XAML"
Text="{x:Bind ViewModel.NewTaskTitle, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<Button
x:Name="AddTaskButton"
Grid.Column="1"
VerticalAlignment="Bottom"
AutomationProperties.Name="Add task"
Command="{x:Bind ViewModel.AddTaskCommand}"
Content="Add task" />
Le libellé visible Header signifie que le champ de saisie ne s’appuie pas sur le texte d’espace réservé comme unique libellé.
UpdateSourceTrigger=PropertyChanged met à jour le modèle de vue à mesure que l’utilisateur tape, afin que la commande puisse être activée immédiatement.
Collection de tâches
Définissez un modèle de données typé :
<DataTemplate x:Key="TaskTemplate" x:DataType="models:TaskItem">
<Grid Padding="8" ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox
VerticalAlignment="Center"
AutomationProperties.Name="{x:Bind Title}"
Click="TaskCheckBox_Click"
IsChecked="{x:Bind IsComplete, Mode=TwoWay}" />
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Text="{x:Bind Title}" />
<Button
Grid.Column="2"
VerticalAlignment="Center"
AutomationProperties.Name="{x:Bind local:MainPage.DeleteTaskName(Title),
Mode=OneWay}"
Click="DeleteButton_Click"
DataContext="{x:Bind}"
ToolTipService.ToolTip="Delete task">
<FontIcon Glyph="" />
</Button>
</Grid>
</DataTemplate>
Utilisez une fonction statique pour inclure le titre de la tâche dans le nom d’automatisation du bouton De suppression, afin qu’un lecteur d’écran puisse faire la distinction entre les lignes :
public static string DeleteTaskName(string title) => $"Delete {title}";
Ensuite, liez la collection :
<ListView
AutomationProperties.Name="Tasks"
ItemTemplate="{StaticResource TaskTemplate}"
ItemsSource="{x:Bind ViewModel.Tasks, Mode=OneWay}"
SelectionMode="None" />
ListView fournit la virtualisation du défilement et de l’interface utilisateur. L’encapsuler dans un ScrollViewer interférent avec les deux.
En savoir plus : ListView et GridView et Liaison de données avec XAML.
État et état vide
Utiliser InfoBar pour un message d’état non bloquant :
<InfoBar
IsClosable="True"
IsOpen="{x:Bind ViewModel.IsStatusOpen, Mode=TwoWay}"
Message="{x:Bind ViewModel.StatusMessage, Mode=OneWay}"
Severity="{x:Bind local:MainPage.StatusSeverity(ViewModel.HasError),
Mode=OneWay}" />
Utilisez une fonction statique pour convertir le booléen Visibility à état vide sans ajouter de classe de convertisseur :
public static Visibility BoolToVisibility(bool value) =>
value ? Visibility.Visible : Visibility.Collapsed;
public static InfoBarSeverity StatusSeverity(bool hasError) =>
hasError ? InfoBarSeverity.Error : InfoBarSeverity.Success;
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="Add a task to get started."
Visibility="{x:Bind local:MainPage.BoolToVisibility(ViewModel.HasNoTasks),
Mode=OneWay}" />
Exécutez l’application avant d’ajouter des données et vérifiez que l’état vide est clair et que le bouton Ajouter une tâche est désactivé :
Disposition adaptative
Utilisez des états visuels pour déplacer le bouton sous l’entrée :
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Narrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="AddTaskButton.(Grid.Row)" Value="1" />
<Setter Target="AddTaskButton.(Grid.Column)" Value="0" />
<Setter Target="AddTaskButton.HorizontalAlignment" Value="Stretch" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Standard">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="640" />
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Redimensionnez l’application en cours d’exécution au-delà du point de rupture. Le fait d’affirmer dans un prompt qu’un contenu est responsive ne prouve pas que la mise en page fonctionne.
En savoir plus : dispositions réactives avec XAML.
Connecter des événements spécifiques à l’affichage
La page charge les données persistantes une fois et délègue les modifications apportées au modèle d’affichage :
public sealed partial class MainPage : Page
{
public MainPageViewModel ViewModel { get; } = new();
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Loaded -= MainPage_Loaded;
await ViewModel.InitializeAsync();
NewTaskTextBox.Focus(FocusState.Programmatic);
}
private async void TaskCheckBox_Click(object sender, RoutedEventArgs e)
{
await ViewModel.TaskCompletionChangedAsync();
}
private async void DeleteButton_Click(object sender, RoutedEventArgs e)
{
if (sender is Button { DataContext: TaskItem task })
{
await ViewModel.DeleteTaskCommand.ExecuteAsync(task);
}
}
}
Les gestionnaires d’événements avec un type de async void retour sont appropriés ici, car les événements XAML nécessitent void. D’autres méthodes asynchrones dans l’application retournent Task.
Compiler et exécuter
Générez l’application, la lancez-la via son package et testez chaque critère d’acceptation qui est désormais implémenté :
- Ajoutez une tâche avec la souris.
- Ajoutez une tâche à l’aide uniquement du clavier.
- Terminez et supprimez une tâche.
- Fermez et redémarrez l’application pour vérifier la persistance.
- Redimensionnez la fenêtre ci-dessous et au-dessus de 640 pixels effectifs.
- Basculez entre un thème clair, sombre et contrasté.
Windows developer