Aktualisierung durch Ziehen

Mithilfe der Aktion „Aktualisieren durch Ziehen“ können Benutzer eine Datenliste per Toucheingabe nach unten ziehen, um weitere Daten abzurufen. Die Aktion „Aktualisieren durch Ziehen“ wird häufig auf Geräten mit Touchscreen verwendet. Sie können die hier gezeigten APIs zum Implementieren von „Aktualisieren durch Ziehen“ in Ihre App verwenden.

GIF zu „Aktualisieren durch Ziehen“

Ist dies das richtige Steuerelement?

Verwenden Sie „Aktualisieren durch Ziehen“ für Datenlisten oder -raster, die vom Benutzer regelmäßig aktualisiert werden, vor allem, wenn die App hauptsächlich auf Geräten mit Touchscreen ausgeführt werden soll.

Sie können auch den RefreshVisualizer verwenden, um eine konsistente Aktualisierungsoption zu erstellen, die auf andere Weise, wie z. B. durch eine Aktualisierungsschaltfläche aufgerufen wird.

Aktualisierungssteuerelemente

„Aktualisieren durch Ziehen“ wird durch zwei Steuerelemente aktiviert.

  • RefreshContainer – Ein ContentControl, das einen Wrapper für das Aktualisieren-durch-Ziehen-Erlebnis bereitstellt. Es verarbeitet die Interaktionen per Toucheingabe und verwaltet den Zustand des internen Visualizers für Aktualisierungen.
  • RefreshVisualizer – Kapselt die Aktualisierungsvisualisierung, die im nächsten Abschnitt erläutert wird.

Das wichtigste Steuerelement ist RefreshContainer, das Sie als Wrapper um den Inhalt platzieren, den der Benutzer abruft, um eine Aktualisierung auszulösen. Da RefreshContainer nur mit Toucheingabe funktioniert, wird empfohlen, dass Sie auch eine Aktualisierungsschaltfläche für Benutzer bereitstellen, die über keinen Touchscreen verfügen. Sie können die Aktualisierungsschaltfläche an einer geeigneten Stelle in der App positionieren, entweder auf einer Befehlsleiste oder in der Nähe der Oberfläche, die aktualisiert wird.

Visualisierung aktualisieren

Die Visualisierung der Standardaktualisierung ist ein kreisförmiges Fortschritts-Drehfeld, das über den Zeitpunkt einer Aktualisierung und deren Fortschritt informiert, nachdem diese gestartet wurde. Der Aktualisierungs-Visualizer verfügt über fünf Zustände.

Der Abstand, den der Benutzer benötigt, um eine Liste zum Initiieren einer Aktualisierung nach unten zu ziehen, wird als Schwellenwert bezeichnet. Der Visualizer Zustand wird anhand des Ziehstatus im Zusammenhang mit diesen Schwellenwert bestimmt. Die möglichen Werte sind in der RefreshVisualizerState-Enumeration enthalten.

Idle

Der Standardzustand des Visualizers ist Leerlauf. Der Benutzer interagiert nicht per Toucheingabe mit dem RefreshContainer, und es wird gerade keine Aktualisierung ausgeführt.

Visuell gibt es keinen Nachweis für den Aktualisierungs-Visualizer.

Interaktion

Wenn der Benutzer die Liste in die von der PullDirection-Eigenschaft angegebene Richtung zieht und sich der Visualizer im Zustand Interaktion befindet, bevor der Schwellenwert erreicht wird.

  • Wenn der Benutzer das Steuerelement loslässt, während es sich in diesem Zustand befindet, kehrt das Steuerelement in den Leerlauf zurück.

    Aktualisierung durch Ziehen vor dem Schwellenwert

    Das Symbol wird visuell als deaktiviert (Deckkraft von 60 %) angezeigt. Darüber hinaus wird das Symbol mit der Scrollen-Aktion einmal vollständig gedreht.

  • Wenn der Benutzer die Liste über den Schwellenwert hinaus zieht, wechselt der Visualizer von Interaktion in Ausstehend.

    Aktualisierung durch Ziehen am Schwellenwert

    Das Symbol wechselt während des Übergangs zu einer Deckkraft von 100 % visuell und pulsiert bis zu einer Größe von 150 % und wieder zurück zu einer Größe von 100 %.

Pending

Wenn der Benutzer die Liste über den Schwellenwert hinaus gezogen hat, befindet sich der Visualizer im Zustand Ausstehend.

  • Wenn der Benutzer die Liste wieder über den Schwellenwert hinaus zieht, ohne sie loszulassen, kehrt sie in den Zustand Interaktion zurück.
  • Wenn der Benutzer die Liste loslässt, wird eine Aktualisierungsanforderung initiiert und sie wechselt in den Zustand Aktualisierung.

Aktualisierung durch Ziehen nach dem Schwellenwert

Visuell weist das Symbol eine Größe und Deckkraft von 100 % auf. In diesem Zustand bewegt sich das Symbol mit der Aktion „Bildlauf“ weiterhin nach unten, dreht sich jedoch nicht mehr.

Wird aktualisiert

Wenn der Benutzer den Visualizer in einer über den Schwellenwert hinausgehenden Position freigibt, befindet er sich im Zustand Aktualisierung.

Wenn dieser Zustand erreicht ist, wird das RefreshRequested-Ereignis ausgelöst. Dies ist das Signal für den Start der Aktualisierung des App-Inhalts. Die Ereignisargumente (RefreshRequestedEventArgs) enthalten das Objekt Verzögerung, für das Sie ein Handle im Ereignishandler verwenden sollten. Anschließend sollten Sie die Verzögerung als abgeschlossen markieren, wenn der Code zum Ausführen der Aktualisierung abgeschlossen ist.

Wenn die Aktualisierung abgeschlossen ist, kehrt der Visualizer in den Zustand Leerlauf zurück.

Visuell kehrt das Symbol zur Schwellenwertposition zurück und dreht sich für die Dauer der Aktualisierung. Diese Drehung dient dazu, den Fortschritt der Aktualisierung anzuzeigen, und wird durch die Animation des eingehenden Inhalts ersetzt.

Einsehen

Wenn der Benutzer von einer Startposition, an der eine Aktualisierung unzulässig ist, in die Aktualisierungsrichtung zieht, wechselt der Visualizer in den Zustand Einsehen. Dies geschieht in der Regel auf, wenn der ScrollViewer sich nicht an der Position 0 befindet, wenn der Benutzer den Ziehvorgang startet.

  • Wenn der Benutzer das Steuerelement loslässt, während es sich in diesem Zustand befindet, kehrt das Steuerelement in den Leerlauf zurück.

Ziehrichtung

Der Benutzer zieht eine Liste standardmäßig von oben nach unten, um eine Aktualisierung zu initiieren. Wenn Sie über eine Liste oder ein Raster mit einer anderen Ausrichtung verfügen, sollten Sie die Ziehrichtung des Aktualisierungs-Containers entsprechend ändern.

Die PullDirection Eigenschaft nimmt einen der folgenden RefreshPullDirection Werte an: BottomToTop, TopToBottom, RightToLeft oder LeftToRight.

Wenn Sie die Pullrichtung ändern, wird die Startposition des Fortschrittsdrehers der Schnellansicht automatisch gedreht, sodass der Pfeil an der für die Pullrichtung geeigneten Position beginnt. Bei Bedarf können Sie die RefreshVisualizer.Orientation-Eigenschaft ändern, um das automatische Verhalten außer Kraft zu setzen. In den meisten Fällen empfiehlt es sich, den Standardwert Auto beizubehalten.

UWP und WinUI 2

Wichtig

Die Informationen und Beispiele in diesem Artikel sind für Apps optimiert, die das Windows App SDK und WinUI 3 verwenden, gelten jedoch allgemein für UWP-Apps, die WinUI 2 verwenden. In der UWP-API-Referenz finden Sie plattformspezifische Informationen und Beispiele.

Dieser Abschnitt enthält Informationen, die Sie zum Verwenden des Steuerelements in einer UWP- oder WinUI 2-App benötigen.

Die Aktualisierungssteuerelemente für UWP-Apps sind als Teil der Windows-UI-Bibliothek 2 enthalten. Weitere Informationen, einschließlich Installationsanweisungen, finden Sie unter Windows UI Library (Windows-UI-Bibliothek). APIs für dieses Steuerelement sind in den Namespaces Windows.UI.Xaml.Controls (UWP) und Microsoft.UI.Xaml.Controls (WinUI) vorhanden.

Es wird empfohlen, die neueste WinUI 2-Version zu verwenden, um die aktuellsten Formatvorlagen, Vorlagen und Features für alle Steuerelemente abzurufen.

Zur Verwendung des Codes in diesem Artikel mit WinUI 2 stellen Sie die in Ihrem Projekt enthaltenen Windows-UI-Bibliothek-APIs mithilfe eines Alias in XAML dar (wir verwenden muxc). Weitere Informationen finden Sie unter Erste Schritte mit WinUI 2.

xmlns:muxc="using:Microsoft.UI.Xaml.Controls"

<muxc:RefreshContainer />

Implementieren von Aktualisierung durch Ziehen

Die WinUI 3-Katalog-App umfasst interaktive Beispiele für die meisten WinUI 3-Steuerelemente, -Features und -Funktionen. Laden Sie die App aus dem Microsoft Store herunter, oder rufen Sie den Quellcode auf GitHub ab.

Um einer Liste die Funktionalität „Aktualisierung durch Ziehen“ hinzuzufügen, müssen nur wenige Schritte ausgeführt werden.

  1. Umschließen Sie Ihre Liste in einem RefreshContainer-Steuerelement.
  2. Behandeln Sie das RefreshRequested-Ereignis, um Ihre Inhalte zu aktualisieren.
  3. Initiieren Sie optional eine Aktualisierung durch Aufrufen von RequestRefresh (z. B. durch Klicken auf eine Schaltfläche).

Hinweis

Sie können einen eigenständigen RefreshVisualizer instanziieren. Es empfiehlt sich jedoch, Ihre Inhalte in einem RefreshContainer zu umschließen und den von der RefreshContainer.Visualizer-Eigenschaft bereitgestellten RefreshVisualizer auch für Szenarien ohne Touchscreen zu verwenden. In diesem Artikel wird davon ausgegangen, dass der Visualizer immer aus dem Aktualisierungs-Container abgerufen wird.

Verwenden Sie außerdem der Einfachheit halber die RequestRefresh- und RefreshRequested-Elemente des Containers. refreshContainer.RequestRefresh() entspricht refreshContainer.Visualizer.RequestRefresh() und löst sowohl das RefreshContainer.RefreshRequested-Ereignis als auch die RefreshVisualizer.RefreshRequested-Ereignisse aus.

Anfordern einer Aktualisierung

Der Aktualisierungs-Container verarbeitet Touchinteraktionen, damit Benutzer Inhalte per Toucheingabe aktualisieren können. Es wird empfohlen, dass Sie andere Angebote für Schnittstellen bereitstellen, die keine Toucheingabe unterstützen, z. B. eine Aktualisierungsschaltfläche oder Sprachsteuerung.

Rufen Sie zum Initiieren einer Aktualisierung die RequestRefresh-Methode auf.

// See the Examples section for the full code.
private void RefreshButtonClick(object sender, RoutedEventArgs e)
{
    RefreshContainer.RequestRefresh();
}

Beim Aufruf von RequestRefresh wechselt der Visualizer-Zustand direkt von Leerlauf zu Aktualisierung.

Verarbeiten einer Aktualisierungsanforderung

Behandeln Sie das RefreshRequested-Ereignis, um aktualisierte Inhalte abzurufen. Im Ereignishandler benötigen Sie Code, der für Ihre App spezifisch ist, um die aktualisierten Inhalte abzurufen.

Die Ereignisargumente (RefreshRequestedEventArgs) enthalten ein Verzögerung-Objekt. Rufen Sie im Ereignishandler einen Handle für die Verzögerung ab. Markieren Sie die Verzögerung anschließend als abgeschlossen, wenn der Code zum Ausführen der Aktualisierung abgeschlossen ist.

// See the Examples section for the full code.
private async void RefreshContainer_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)
{
    // Respond to a request by performing a refresh and using the deferral object.
    using (var RefreshCompletionDeferral = args.GetDeferral())
    {
        // Do some async operation to refresh the content

         await FetchAndInsertItemsAsync(3);

        // The 'using' statement ensures the deferral is marked as complete.
        // Otherwise, you'd call
        // RefreshCompletionDeferral.Complete();
        // RefreshCompletionDeferral.Dispose();
    }
}

Reagieren auf Zustandsänderungen

Sie können bei Bedarf auf Änderungen des Visualizer-Zustands reagieren. Um mehrere Aktualisierungsanforderungen zu verhindern, können Sie eine Aktualisierungsschaltfläche während der Aktualisierung des Visualizers deaktivieren.

// See the Examples section for the full code.
private void Visualizer_RefreshStateChanged(RefreshVisualizer sender, RefreshStateChangedEventArgs args)
{
    // Respond to visualizer state changes.
    // Disable the refresh button if the visualizer is refreshing.
    if (args.NewState == RefreshVisualizerState.Refreshing)
    {
        RefreshButton.IsEnabled = false;
    }
    else
    {
        RefreshButton.IsEnabled = true;
    }
}

Verwenden von ScrollViewer in einem RefreshContainer

Hinweis

Der Inhalt eines RefreshContainer muss ein scrollbares Steuerelement sein, z.B. ScrollViewer, GridView, ListView usw. Das Festlegen des Inhalts auf ein Steuerelement wie Grid führt zu einem nicht definierten Verhalten.

Anhand dieses Beispiels wird veranschaulicht, wie Sie „Aktualisierung durch Ziehen“ mit einer Bildlaufanzeige verwenden.

<RefreshContainer>
    <ScrollViewer VerticalScrollMode="Enabled"
                  VerticalScrollBarVisibility="Auto"
                  HorizontalScrollBarVisibility="Auto">
 
        <!-- Scrollviewer content -->

    </ScrollViewer>
</RefreshContainer>

Hinzufügen von „Aktualisierung durch Ziehen“ zu einer ListView

Anhand dieses Beispiels wird veranschaulicht, wie Sie „Aktualisierung durch Ziehen“ mit einer Listenansicht verwenden.

<StackPanel Margin="0,40" Width="280">
    <CommandBar OverflowButtonVisibility="Collapsed">
        <AppBarButton x:Name="RefreshButton" Click="RefreshButtonClick"
                      Icon="Refresh" Label="Refresh"/>
        <CommandBar.Content>
            <TextBlock Text="List of items" 
                       Style="{StaticResource TitleTextBlockStyle}"
                       Margin="12,8"/>
        </CommandBar.Content>
    </CommandBar>

    <RefreshContainer x:Name="RefreshContainer">
        <ListView x:Name="ListView1" Height="400">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:ListItemData">
                    <Grid Height="80">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <TextBlock Text="{x:Bind Path=Header}"
                                   Style="{StaticResource SubtitleTextBlockStyle}"
                                   Grid.Row="0"/>
                        <TextBlock Text="{x:Bind Path=Date}"
                                   Style="{StaticResource CaptionTextBlockStyle}"
                                   Grid.Row="1"/>
                        <TextBlock Text="{x:Bind Path=Body}"
                                   Style="{StaticResource BodyTextBlockStyle}"
                                   Grid.Row="2"
                                   Margin="0,4,0,0" />
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </RefreshContainer>
</StackPanel>
public sealed partial class MainPage : Page
{
    public ObservableCollection<ListItemData> Items { get; set; } 
        = new ObservableCollection<ListItemData>();

    public MainPage()
    {
        this.InitializeComponent();

        Loaded += MainPage_Loaded;
        ListView1.ItemsSource = Items;
    }

    private async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        Loaded -= MainPage_Loaded;
        RefreshContainer.RefreshRequested += RefreshContainer_RefreshRequested;
        RefreshContainer.Visualizer.RefreshStateChanged += Visualizer_RefreshStateChanged;

        // Add some initial content to the list.
        await FetchAndInsertItemsAsync(2);
    }

    private void RefreshButtonClick(object sender, RoutedEventArgs e)
    {
        RefreshContainer.RequestRefresh();
    }

    private async void RefreshContainer_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)
    {
        // Respond to a request by performing a refresh and using the deferral object.
        using (var RefreshCompletionDeferral = args.GetDeferral())
        {
            // Do some async operation to refresh the content

            await FetchAndInsertItemsAsync(3);

            // The 'using' statement ensures the deferral is marked as complete.
            // Otherwise, you'd call
            // RefreshCompletionDeferral.Complete();
            // RefreshCompletionDeferral.Dispose();
        }
    }

    private void Visualizer_RefreshStateChanged(RefreshVisualizer sender, RefreshStateChangedEventArgs args)
    {
        // Respond to visualizer state changes.
        // Disable the refresh button if the visualizer is refreshing.
        if (args.NewState == RefreshVisualizerState.Refreshing)
        {
            RefreshButton.IsEnabled = false;
        }
        else
        {
            RefreshButton.IsEnabled = true;
        }
    }

    // App specific code to get fresh data.
    private async Task FetchAndInsertItemsAsync(int updateCount)
    {
        for (int i = 0; i < updateCount; ++i)
        {
            // Simulate delay while we go fetch new items.
            await Task.Delay(1000);
            Items.Insert(0, GetNextItem());
        }
    }

    private ListItemData GetNextItem()
    {
        return new ListItemData()
        {
            Header = "Header " + DateTime.Now.Second.ToString(),
            Date = DateTime.Now.ToLongDateString(),
            Body = DateTime.Now.ToLongTimeString()
        };
    }
}

public class ListItemData
{
    public string Header { get; set; }
    public string Date { get; set; }
    public string Body { get; set; }
}

Beispielcode herunterladen