Erişilebilir ve uyarlamalı arabirimi oluşturma

Şimdi yardımcıdan sayfayı oluşturmasını isteyin. İstediğiniz WinUI denetimlerini adlandırarak başka bir UI çerçevesinin denetiminin yerini tutmamasını sağlayın.

XAML'yi isteyin

Şu istemi kullanın:

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.

Oluşturulan XAML'de bu ayrıntıları inceleyin.

Veri girişi

<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" />

Görünür Header, girişin etiket olarak yalnızca yer tutucu metni kullanmadığı anlamına gelir. UpdateSourceTrigger=PropertyChanged görünüm modelini kullanıcı türü olarak güncelleştirerek komutun hemen etkinleştirilebilmesini sağlar.

Görev koleksiyonu

Yazılan bir veri şablonu tanımlayın:

<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="&#xE74D;" />
        </Button>
    </Grid>
</DataTemplate>

Ekran okuyucunun satırları ayırt edebilmesi için, sil düğmesinin otomasyon adına görev başlığını eklemek için statik bir işlev kullanın:

public static string DeleteTaskName(string title) => $"Delete {title}";

Ardından koleksiyonu bağlayın:

<ListView
    AutomationProperties.Name="Tasks"
    ItemTemplate="{StaticResource TaskTemplate}"
    ItemsSource="{x:Bind ViewModel.Tasks, Mode=OneWay}"
    SelectionMode="None" />

ListView kaydırma ve kullanıcı arabirimi sanallaştırması sağlar. Onu ScrollViewer içine sarmak her ikisine de müdahale eder.

Daha fazla bilgi edinin: XAML ile ListView, GridView ve Veri bağlama.

Durum ve boş ekran durumu

Engellenmeyen durum iletisi için kullanın InfoBar :

<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}" />

Dönüştürücü sınıfı eklemeden boş durum Boole değerini Visibility öğesine dönüştürmek için statik bir işlev kullanın:

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}" />

Veri eklemeden önce uygulamayı çalıştırın ve boş durumun temiz olduğunu ve Görev ekle düğmesinin devre dışı bırakıldığını onaylayın:

Task Tally boş durumunda; yeni görev metin kutusu, devre dışı bırakılmış Görev ekle düğmesi ve ilk görevi eklemeye yönelik yönergeler.

Uyarlamalı düzen

Düğmeyi girişin altına taşımak için görsel durumları kullanın:

<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>

Çalışan uygulamayı kırılma noktasını aşacak şekilde yeniden boyutlandırın. bir istemdeki yanıt veren talep, düzenin çalıştığının kanıtı değildir.

Daha fazla bilgi edinin: XAML ile esnek düzenler.

Görünüme özgü olayları bağlama

Sayfa kalıcı verileri bir kez yükler ve görev değişikliklerini görünüm modeline devreder:

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);
        }
    }
}

async void dönüş türüne sahip olay işleyicileri burada uygundur çünkü XAML olayları void gerektirir. Uygulamadaki diğer asenkron yöntemler Task döndürür.

Derle ve çalıştır

Uygulamayı oluşturun, paketi aracılığıyla başlatın ve şu anda uygulanan tüm kabul ölçütlerini test edin:

  1. Fareyle bir görev ekleyin.
  2. Yalnızca klavyeyi kullanarak bir görev ekleyin.
  3. Görevi tamamlayın ve silin.
  4. Kalıcılığı doğrulamak için uygulamayı kapatın ve yeniden başlatın.
  5. 640 etkin pikselin altındaki ve üzerindeki pencereyi yeniden boyutlandırın.
  6. Açık, koyu ve karşıtlık teması arasında geçiş yapın.