Verwenden von Steuerelementen in Hilo (Windows Store-Apps mit C++ und XAML)

Applies to Windows only

Aus: Umfassende Entwicklung einer Windows Store-App mit C++ und XAML: Hilo

Leitfaden-Logo

Vorherige Seite | Nächste Seite

Steuerelemente sind das Herzstück von Windows 8 und XAML. Hier finden Sie Informationen zu einigen Steuerelementen, einschließlich Image, Grid und GridView, ProgressRing, Button, TextBlock, AppBar, StackPanel, ListView, SemanticZoom, Canvas und ContentControl sowie Popup, und Informationen dazu, wie Bindungen und Stile für die Implementierung der C++-Benutzeroberfläche von Hilo verwendet wurden.

Download

Herunterladen des Hilo-Beispiels
Buch herunterladen (PDF)

Anweisungen zu dem heruntergeladenen Code finden Sie unter Erste Schritte mit Hilo.

Im Einzelnen werden Sie Folgendes lernen:

  • Verknüpfen der Benutzeroberfläche mit CodeBehind unter Verwendung von Bindungen
  • Anwenden von Datenvorlagen
  • Schreiben von benutzerdefinierten Steuerelementen
  • Verarbeiten ungültiger Bilder, wenn Bindungen verwendet werden.
  • Konvertieren der Modelldaten, damit sie richtig angezeigt werden.

Betrifft

  • Windows-Runtime für Windows 8
  • Visual C++-Komponentenerweiterungen (C++/CX)
  • XAML

Möglicherweise haben Sie schon bemerkt, dass sich XAML eher durch einen deklarativen als durch einen imperativen Charakter auszeichnet. XAML erzeugt eine Struktur von Objekten. Sie können sich diese Struktur wie ein DOM in HTML vorstellen. Wenn Sie mit XAML noch nicht so vertraut sind, erhalten Sie unter Schnellstart: Erstellen einer Benutzeroberfläche mit XAML und unter Schnellstart: Hinzufügen von Steuerelementen und Behandeln von Ereignissen weitere Informationen.

Hinweis  Im Thema Erstellen von und Navigieren zwischen Seiten wird erläutert, wie Blend für Visual Studio und der Visual Studio XAML-Designer zum Arbeiten mit XAML-Seiten und -Steuerelementen verwendet werden. Die Tools sind sehr benutzerfreundlich. Achten Sie jedoch darauf, Ihre Steuerelemente nicht übermäßig zu formatieren. Beispielsweise muss nicht jede Schaltfläche über einen Farbverlauf im Hintergrund oder über abgerundete Ecken verfügen. Diesbezügliche Richtlinien mit Informationen finden Sie unter UX-Richtlinien für Windows Store Apps.

Nachstehend werden einige wichtige XAML-Konzepte erläutert, mit denen C++-Entwickler möglicherweise noch nicht vertraut sind:

  • CodeBehind verknüpft XAML-Markup mit kompiliertem Code, der die Logik Ihrer App implementiert. Beispielsweise implementieren Sie für ein Button-Steuerelement den Handler für das Click-Ereignis in Ihrem C++-Code. Dieser C++-Code ist ein Beispiel für CodeBehind.

    Grundsätzlich kann die Logik CodeBehind auch direkt hinzugefügt werden. In Hilo verknüpft CodeBehind das XAML mit Ansichtsmodellen, die die Logik definieren.

  • Eine Vorlage oder Datenvorlage definiert die Struktur, das Layout und die Animationen, die mit einem Steuerelement verbunden sind; darüber hinaus werden auch die Stile definiert. Vorlagen wirken sich auf das Erscheinungsbild eines Steuerelements, nicht jedoch auf dessen Verhalten aus. Beispielsweise stellen Listenfelder ebenso wie die meisten anderen Steuerelemente ihre Datenelemente mit Zeichenfolgen dar. Durch den Einsatz von Vorlagen können Sie Grafiken und andere visuelle Elemente zur Darstellung Ihrer Daten verwenden. Mit der DataTemplate-Klasse wird die visuelle Darstellung von Daten aus XAML definiert.
  • Eine Bindung stellt einen datengebundenen Eigenschaftswert bereit, sodass der Wert bis zur Laufzeit zurückgestellt wird. Mit der Binding-Klasse werden Daten mit Ihrer Benutzeroberfläche verknüpft.
  • Ein benutzerdefiniertes Steuerelement aggregiert Funktionen von anderen Steuerelementen.
  • Ein Datenkonverter wandelt einen Wert in einen anderen um. Mit einem Datenkonverter und einer Bindung können Sie den Wert oder das Format gebundener Daten so ändern, dass diese von Ihrer App angezeigt werden können.
  • Eine Ressource verweist auf Funktionen, die wiederverwendet werden können. Stile, Pinsel und Text, die auf einer Seite angezeigt werden, sind Beispiele für Ressourcen.

Die Programmierung von Windows Store-Apps mit XAML ähnelt der Programmierung mit Windows Presentation Foundation (WPF) und Silverlight. Die wesentlichen Unterschiede bestehen darin, dass Windows Store-Apps auf Fingereingaben ausgelegt sind und mehrere neue Steuerelemente enthalten. Die Unterschiede zwischen Silverlight oder WPF und Windows Store-Apps mit XAML werden unter Portieren von Silverlight- oder WPF XAML-Code in eine Windows Store-App erläutert. In der Liste Steuerelemente und in der Liste Steuerelemente nach Funktion werden alle verfügbaren Steuerelemente einschließlich AppBar, GridView, SemanticZoom sowie der anderen neuen Steuerelemente von Windows 8 aufgeführt.

Hinweis  Windows Store-Apps mit C++ und XAML werden vollständig mit systemeigenem Code ausgeführt. XAML-Steuerelemente werden außerdem durch die Grafikhardware beschleunigt. Die C++/CX-Syntax erleichtert das Entwickeln für die Windows-Runtime; das .NET Framework wird nicht unterstützt. .NET kommt nur dann als Ziel einer C++-App infrage, wenn eine Windows-Runtime-Komponente mit .NET verwendet wird. Weitere Informationen über C++/CX finden Sie unter Schreiben von modernem C++-Code.

[Nach oben]

Datenbindung

Eine Bindung stellt einen datengebundenen Eigenschaftswert bereit, sodass der Wert bis zur Laufzeit zurückgestellt wird. Bindungen sind für den effizienten Einsatz von XAML von zentraler Bedeutung. Sie ermöglichen es, eine deklarative Verbindung zwischen Ihrer Benutzeroberfläche und den Daten herzustellen. Darüber hinaus minimieren Bindungen die Notwendigkeit des Einsatzes von CodeBehind. Da die Daten zur Laufzeit verarbeitet werden, können Sie Ihre Daten und Ihrer Benutzeroberfläche beim Gestalten der App separat verwalten. In Hilo ist das Binden von Daten zur Laufzeit kritisch, da zur Entwurfszeit keine Informationen über die Bildbibliothek des Benutzers vorliegen. Weitere Informationen über Bindungen finden Sie unter Übersicht Datenbindung und unter Binden von Markuperweiterungen.

Das MVVM-Muster wird von Bindungen ebenfalls unterstützt. Weitere Informationen zur Verwendung von Bindungen in Hilo finden Sie unter Verwenden des MVVM-Musters. In den weiteren Abschnitten auf dieser Seite wird außerdem beschrieben, wie Sie statische und dynamische Inhalte verknüpfen können.

[Nach oben]

Datenkonverter

Ein Datenkonverter wandelt einen Wert in einen anderen um. Konverter können den Wert eines Typs in den Wert eines anderen Typs umwandeln oder einfach einen Wert ändern und den gleichen Typ erzeugen.

In Hilo werden Datenkonverter eingesetzt, um den Wert oder das Format gebundener Daten zu ändern, wenn für einen Datentyp spezielle Formatierungen erforderlich sind, die vom Ansichtsmodell nicht bereitgestellt werden. Im Folgenden sind die für Hilo definierten Datenkonverter aufgeführt.

KonvertertypKonvertiert vonKonvertiert nachBeschreibung
BooleanToBrushConverterbool Platform::String In der Kalenderansicht werden damit Monate mit Bildern orange und Monate ohne Bilder grau dargestellt. Der Wert true wird orange (#F19720) und der Wert false wird grau zugeordnet (#E2E2E2). Dies ist möglich, da die Brush-Klasse einen Typkonverter enthält, um den Zeichenfolgenwert in einen Brush umzuwandeln.
FileSizeConverterunsigned long long Platform::String Wandelt Dateigrößen von Byte in Kilobyte oder Megabyte um, um die Lesbarkeit entsprechender Werte zu verbessern.

 

Darüber hinaus stellen die Visual Studio-Projektvorlagen die BooleanNegationConverter- und die BooleanToVisibilityConverter-Klasse bereit. Diese negieren bool-Werte bzw. konvertieren bool-Werte in Visibility-Enumerationswerte. Sie finden diese Klassen im Ordner "Common" der Projektmappe.

Um einen Datenkonverter zu erstellen, können Sie einen von IValueConverter abgeleiteten Typ erstellen. Sie müssen die Convert-Methode und die ConvertBack-Methode sowie alle weiteren Methoden implementieren, die Sie benötigen. Hier finden Sie die Deklaration für die FileSizeConverter-Klasse.

FileSizeConverter.h


[Windows::Foundation::Metadata::WebHostHidden]
public ref class FileSizeConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{
public:
    FileSizeConverter();
    FileSizeConverter(IResourceLoader^ loader);

    virtual Object^ Convert(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object^ parameter, Platform::String^ language);
    virtual Object^ ConvertBack(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Object^ parameter, Platform::String^ language);

private:
    float64 ToTwoDecimalPlaces(float64 value);
    IResourceLoader^ m_loader;
};


Und hier finden Sie die Implementierung.

FileSizeConverter.cpp


Object^ FileSizeConverter::Convert(Object^ value, TypeName targetType, Object^ parameter, String^)
{
    float64 size = static_cast<float64>(safe_cast<uint64>(value));
    std::array<String^, 3> units = 
    { 
        m_loader->GetString("BytesUnit"), 
        m_loader->GetString("KilobytesUnit"), 
        m_loader->GetString("MegabytesUnit") 
    };
    unsigned int index = 0;

    while (size >= 1024)
    {
        size /= 1024;
        index++;
    }

    return ToTwoDecimalPlaces(size) + " " + units[index];
}

float64 FileSizeConverter::ToTwoDecimalPlaces(float64 value)
{
    float64 f;
    float64 intpart;
    float64 fractpart;
    fractpart = modf(value, &intpart);
    f = floor(fractpart * 100 + 0.5) / 100.0;
    return intpart + f;
}

Object^ FileSizeConverter::ConvertBack(Object^ value, TypeName targetType, Object^ parameter, String^)
{
    throw ref new NotImplementedException();
}


In der FileSizeConverter::Convert-Methode wird mit safe_cast eine Konvertierung von Object^ in den Werttyp uint64 durchgeführt. (Wenn bei der Konvertierung ein Fehler auftritt, wird von safe_cast eine Platform::InvalidCastException ausgelöst.) Die Umwandlung in uint64 wird vorgenommen, um den Konverter an die IPhoto::FileSize-Eigenschaft zu binden, die uint64 zurück gibt. Anschließend wird der uint64-Wert in float64 konvertiert, da die Berechnung Gleitkommaarithmetik verwendet.

Die ConvertBack-Methode muss implementiert werden, da sie zur IValueConverter-Schnittstelle gehört. Wir lösen jedoch NotImplementedException aus, um anzugeben, dass diese Funktion nicht implementiert ist. Wenn Sie nicht davon ausgehen, dass die Methode aufgerufen wird, sollten Sie diese Ausnahme auslösen, anstatt einen Standardwert zurückzugeben. Auf diese Weise können Sie während der Entwicklung sicherstellen, dass die Methode niemals aufgerufen wird. Bei Rückgabe eines Standardwerts weist die App möglicherweise ein unerwartetes Verhalten auf. In Hilo wird nicht davon ausgegangen, dass ConvertBack aufgerufen wird, da es sich nicht um eine bidirektionale Bindung handelt. (In einigen Anwendungen können Benutzer in einem Feld, das an einen Datumswert gebunden ist, möglicherweise einen neuen Datumswert eingeben. Damit diese bidirektionale Bindung ordnungsgemäß funktioniert, ist sowohl die Convert- als auch die ConvertBack-Methode erforderlich.)

Um den Konverter für XAML verwenden zu können, muss dieser zunächst Ihrem Ressourcenwörterbuch hinzugefügt werden. Nachfolgend finden Sie ein Beispiel für die Bildansicht.

ImageView.xaml


<Page.Resources>
    <local:FileSizeConverter x:Key="FileSizeConverter" />
    <Style x:Key="FilmStripGridViewItemStyle" 
           BasedOn="{StaticResource HiloGridViewItemStyle}" 
           TargetType="GridViewItem">
        <Setter Property="Margin" Value="0,0,2,4" />
    </Style>
</Page.Resources>


Außerdem müssen Sie die Headerdatei für den Konverter im CodeBehind für die Seite hinzufügen.

ImageView.xaml.h


#include "FileSizeConverter.h" // Required by generated header
#include "ImageView.g.h"


Um einen gebundenen Wert zu konvertieren, verwenden Sie die Binding::Converter-Eigenschaft von XAML. In diesem Beispiel wird mit FileSizeConverter die Bildgröße auf dem Datenträger angepasst, um die Erkennung in Popups zu erleichtern, die zum Anzeigen zusätzlicher Dateiinformationen verwendet werden. (Weitere Informationen zu entsprechenden Popups finden Sie in diesem Leitfaden unter Gedrückt halten: Lernen.)

ImageView.xaml


<TextBlock Foreground="{StaticResource ApplicationForegroundThemeBrush}" 
           Text="{Binding Path=CurrentPhotoImage.FileSize, Converter={StaticResource FileSizeConverter}}" />


Weitere Informationen über Datenkonverter finden Sie unter Übersicht Datenbindung.

[Nach oben]

Häufig verwendete Hilo-Steuerelemente

Nachfolgend sind einige Steuerelemente aufgelistet, die häufig in Hilo verwendet werden. Sie können auch auf die XAML-Dateien im Ordner Views des Visual Studio-Projekts zurückgreifen.

Tipp  Alle verfügbaren Steuerelemente finden Sie in der Liste Steuerelemente und in der Liste Steuerelemente nach Funktion. Sie können diese Seite als Lesezeichen hinzufügen, damit Sie schneller wieder dorthin zurückkehren können, wenn Sie Ihrer App weitere Features hinzufügen möchten. Sie können auch das Fenster Toolbox in Visual Studio und die Registerkarte Assets in Blend für Visual Studio verwenden, um nach Steuerelementen zu suchen und diese Ihren Seiten hinzuzufügen.

Image

Mit dem Image-Steuerelement werden Bilder in der App angezeigt. Das Festlegen der Größe, Ausrichtung und anderer Anzeigeeigenschaften erschien damit relativ unkompliziert möglich. Eigenschaften wie die Größe werden dabei nicht in jedem Fall angegeben, damit das Bild vom Framework an den verfügbaren Platz angepasst werden kann. Wenn die Größe eines untergeordneten Elements für ein Grid-Steuerelement beispielsweise nicht explizit festgelegt wird, wird das Element gestreckt, sodass es den zur Verfügung stehenden Platz in der Rasterzelle ausfüllt. Weitere Informationen über die Layouteigenschaften häufig verwendeter Steuerelemente finden Sie unter Schnellstart: Hinzufügen von Layoutsteuerelementen.

Bildsteuerelement

Hier ist der XAML-Code für den Image.

CropImageView.xaml


<Image x:Name="Photo" 
       AutomationProperties.AutomationId="ImageControl"
       HorizontalAlignment="Center" 
       VerticalAlignment="Center" 
       SizeChanged="OnSizeChanged"
       Source="{Binding Image}"/>


Da es sich bei den Bildern üblicherweise um Fotos des Anwenders handelt, erschien uns die Verwendung einer Bindung sehr hilfreich. Auf diese Weise können die Elemente angegeben werden, die geladen werden sollen, ohne CodeBehind schreiben zu müssen. Darüber hinaus müssen auch Bilddateien verarbeitet werden, die nicht geladen werden können. (Beispiel: beschädigte Bilddateien.) Die Photo-Klasse von Hilo ist an das Ansichtsmodell gebunden und stellt die Bilddaten bereit. Außerdem abonniert sie das Image::ImageFailed-Ereignis. Dieses Ereignis wird aufgerufen, wenn es beim Abrufen von Bildern zu Fehlern kommt.

PhotoImage.cpp


m_image = ref new BitmapImage();
m_imageFailedEventToken = m_image->ImageFailed::add(ref new ExceptionRoutedEventHandler(this, &PhotoImage::OnImageFailedToOpen));


Der Handler für das Image::ImageFailed-Ereignis (PhotoImage::OnImageFailedToOpen) lädt mit der ms-appx://-Syntax ein Standardbild, wenn es beim Abrufen von Bildern zu Fehlern kommt.

PhotoImage.cpp


void PhotoImage::OnImageFailedToOpen(Object^ sender, ExceptionRoutedEventArgs^ e)
{
    assert(IsMainThread());

    // Load a default image.
    ClearImageData();
    m_image = ref new BitmapImage(ref new Uri("ms-appx:///Assets/HiloLogo.png"));  
    OnPropertyChanged("Image");
}


Weitere Informationen über ms-appx:// und andere URI-Schemas finden Sie unter So wird's gemacht: Laden von Dateiressourcen.

Im nächsten Abschnitt wird beschrieben, wie mithilfe einer Bindung der Bildstreifen auf der Bildseite angezeigt wird.

Weitere Informationen über Bilder finden Sie unter Schnellstart: Image und ImageBrush, Beispiel für XAML-Bilder und Beispiel für wichtige XAML-Steuerelemente.

Grid und GridView

Raster bilden die Grundlage aller Seiten in der Hilo-App. Sie ermöglichen es, untergeordnete Steuerelemente an jeder beliebigen Stelle zu positionieren. Ein Grid ist ein Layoutpanel, das die Anordnung von untergeordneten Elementen in Zeilen und Spalten unterstützt. Eine GridView stellt eine Sammlung von Elementen in Zeilen und Spalten dar, für die ein horizontaler Bildlauf durchgeführt werden kann. Mit einem GridView können auch Sammlungen variabler Größe angezeigt werden.

Grid wurde verwendet, um eine festgelegte Anzahl von Elementen anzuzeigen, die alle Platz auf dem Bildschirm haben. GridView wurde verwendet, um Sammlungen variabler Größe anzuzeigen. Beispielsweise wurden Fotos auf der Bildbrowserseite mithilfe von GridView nach Monaten angeordnet. Außerdem wird mit GridView der Bildstreifen angezeigt, der auf der Bildseite in der Navigationsleiste erscheint.

Bildstreifen oben in der App-Leiste

Hier ist das XAML für GridView, das den Bildstreifen darstellt.

ImageView.xaml


<GridView x:Name="PhotosFilmStripGridView"
          Grid.Column="1"
          AutomationProperties.AutomationId="PhotosFilmStripGridView"
          IsItemClickEnabled="False"
          ItemContainerStyle="{StaticResource FilmStripGridViewItemStyle}"
          ItemsSource="{Binding Photos}"
          SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}"
          SelectionMode="Single"
          VerticalAlignment="Center">
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Height="138" Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
    <GridView.ItemTemplate>
        <DataTemplate>
            <Border>
                <Image Source="{Binding Path=Thumbnail}" 
                       Height="138" 
                       Width="200" 
                       Stretch="UniformToFill" />
            </Border>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>


Hinweis  Das x:Name-Attribut gibt den Namen der Steuerelementinstanz für den Code an. Im vorliegenden Beispiel generiert der Compiler die Membervariable PhotosFilmStripGridView für die ImageView-Klasse. Diese Membervariable wird in der Datei "ImageView.g.h" angezeigt, die vom Compiler generiert wird.

Diese GridView passt mithilfe von FilmStripGridViewItemStyle (definiert in der Datei "ApplicationStyles.xaml") die Darstellung von GridViewItem an, die in der GridView angezeigt werden. Jedes GridViewItem stellt ein Image-Steuerelement dar, das in ein Border-Steuerelement eingeschlossen ist und in der DataTemplate des GridView definiert wird. Um die Virtualisierung der Benutzeroberfläche zu unterstützen, werden die GridViewItem mit einem (in der ItemsPanelTemplate des GridView definierten) VirtualizingStackPanel angezeigt. Weitere Informationen über die Virtualisierung der Benutzeroberfläche finden Sie in diesem Leitfaden unter Virtualisierung der Benutzeroberfläche beim Arbeiten mit umfangreicheren Datensätzen.

Im nächsten Beispiel wird veranschaulicht, wie das ausgewählte Element mit der ImageView::OnFilmStripLoaded-Methode per Bildlauf in die Ansicht verschoben wird.

ImageView.xaml.cpp


// Scrolls the selected item into view after the collection is likely to have loaded.
void ImageView::OnFilmStripLoaded(Object^ sender, RoutedEventArgs^ e)
{
    auto vm = dynamic_cast<ImageViewModel^>(DataContext);
    if (vm != nullptr)
    {
        PhotosFilmStripGridView->ScrollIntoView(vm->SelectedItem);
    }

    PhotosFilmStripGridView->Loaded::remove(m_filmStripLoadedToken);
}


Ein interessanter Aspekt von GridView ist die Art und Weise der Datenbindung. Um MVVM auf der Bildbetrachtungsseite zu aktivieren, wird der DataContext der Seiten auf die ImageVM-Eigenschaft der ViewModelLocator-Klasse festgelegt. (Weitere Informationen über MVVM finden Sie unter Verwenden des MVVM-Musters) .

ImageView.xaml


<local:HiloPage
    x:Name="pageRoot"
    x:Uid="Page"
    x:Class="Hilo.ImageView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Hilo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=ImageVM}">


Darauf hin werden untergeordnete Steuerelemente der Seite an die ImageViewModel-Klasse gebunden (und die ViewModelLocator::ImageVM-Eigenschaft gibt ein ImageViewModel-Objekt zurück). Für den Bildstreifen wird eine Bindung mit der ImageViewModel::Photos-Eigenschaft hergestellt, um die Fotos des aktuellen Monats anzuzeigen.

ImageView.xaml


<GridView x:Name="PhotosFilmStripGridView"
          Grid.Column="1"
          AutomationProperties.AutomationId="PhotosFilmStripGridView"
          IsItemClickEnabled="False"
          ItemContainerStyle="{StaticResource FilmStripGridViewItemStyle}"
          ItemsSource="{Binding Photos}"
          SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}"
          SelectionMode="Single"
          VerticalAlignment="Center">


Die ImageViewModel::Photos-Eigenschaft ist eine Sammlung von IPhoto-Objekten. Um ein einzelnes Foto anzuzeigen, wird ein Image-Element verwendet, das an die IPhoto::Thumbnail-Eigenschaft gebunden ist.

ImageView.xaml


<GridView.ItemTemplate>
    <DataTemplate>
        <Border>
            <Image Source="{Binding Path=Thumbnail}" 
                   Height="138" 
                   Width="200" 
                   Stretch="UniformToFill" />
        </Border>
    </DataTemplate>
</GridView.ItemTemplate>


Die Bindung zwischen der Ansicht und dem Ansichtsmodell wird zur Laufzeit beim Erstellen der Seite hergestellt. Wenn Benutzer zu der Seite navigieren, wird die Dateisystemabfrage durch die ImageViewModel::OnNavigatedTo-Methode auf die Bilder des aktuellen Monats festgelegt. Wenn das GridView zum ersten Mal die Bilder für den aktuellen Monat anzeigt, ruft die ImageViewModel::Photos-Eigenschaft die ImageViewModel::OnDataChanged-Methode auf, die wiederum die ImageViewModel::QueryPhotosAsync-Methode aufruft. Die ImageViewModel::QueryPhotosAsync-Methode ruft GetPhotosForDateRangeQueryAsync für die freigegebene Instanz des Zeigers der FileSystemRepository-Klasse auf. Diese wurde an den ImageViewModel-Konstruktor übergeben und übergibt die m_query-Membervariable mit der Dateisystemabfrage für die Bilder des aktuellen Monats.

Weitere Informationen über die GridView finden Sie unter Hinzufügen von ListView- und GridView-Steuerelementen und Elementvorlagen für Rasterlayouts.

ProgressRing

Mit dem ProgressRing-Steuerelement wird angegeben, dass ein Vorgang gerade ausgeführt wird. Alle langfristigen Vorgänge werden im Hintergrund ausgeführt, um dem Benutzer die Interaktion mit der App zu ermöglichen. Außerdem werden Statusringe eingesetzt, um anzuzeigen, dass ein Vorgang ausgeführt und in Kürze abgeschlossen sein wird. Verwenden Sie Statussteuerelemente, wenn der Abschluss eines Vorgangs voraussichtlich 2 Sekunden oder länger dauert.

Hier ist das XAML für die Bildbrowserseite. Der Statusring wird beim Laden von Miniaturbilddaten durch das Betriebssystem angezeigt.

ImageBrowserView.xaml


<ProgressRing x:Name="ProgressRing" 
              IsActive="{Binding InProgress}" 
              Height="60"
              Width="60"
              Foreground="{StaticResource HiloHighlightBrush}"/>


Wir binden die IsActive-Eigenschaft an die ImageBrowserViewModel::InProgress-Eigenschaft (boolescher Wert). Wenn das Ansichtsmodell Bilder vom Betriebssystem abruft, gibt die ImageBrowserViewModel::InProgress-Eigenschaft true zurück. Nach Abschluss der Abfrage wird false von der ImageBrowserViewModel::InProgress-Eigenschaft zurückgegeben. Außerdem löst das Ansichtsmodellobjekt das PropertyChanged-Ereignis aus. Dadurch wird die XAML-Laufzeit angewiesen, den Statusring auszublenden.

Das ProgressRing-Steuerelement wird anstelle des ProgressBar-Steuerelements verwendet, um anzugeben, dass ein Vorgang gerade ausgeführt wird, da die Zeit bis zum Abschluss des Vorgangs nicht bekannt ist. Mit ProgressBar können Sie detailliertere Informationen über die Zeit bis zum Abschluss des Vorgangs angeben. Statusleisten oder -ringe dürfen nicht verhindern, dass Benutzer einen Vorgang abbrechen oder zu einer anderen Seite navigieren können. Weitere Informationen über das Durchführen und Abbrechen von Hintergrundvorgängen finden Sie unter Asynchrone Programmiermuster in C++.

Hinweis  Legen Sie die ProgressRing::IsActive- und die ProgressBar::IsIndeterminate-Eigenschaft nach dem Anzeigen der Statusinformationen immer auf false fest. Auch wenn diese Steuerelemente nicht sichtbar sind, können ihre Animationen CPU-Zyklen beanspruchen und zu Leistungseinbußen führen oder die Akkulaufzeit verkürzen. Außerdem wird der ProgressRing zwar nicht angezeigt, wenn ProgressRing::IsActive auf false festgelegt ist; dennoch ist der entsprechende Platz auf der Benutzeroberfläche reserviert. Legen Sie die entsprechende Visibility-Eigenschaft auf Collapsed, um zu verhindern, dass Speicherplatz für den ProgressRing reserviert wird.

Weitere Richtlinien für Statussteuerelemente finden Sie unter Richtlinien und Prüfliste für Statussteuerelemente.

Schaltfläche

Ein Button-Steuerelement reagiert auf Benutzereingaben und löst ein Click-Ereignis aus. In Hilo werden Schaltflächen für folgende Zwecke verwendet:

  • Definieren einer Zurück-Schaltfläche auf jeder Seite.
  • Ermöglichen der Benutzernavigation von der Hubseite zur Bildersuchseite.
  • Ermöglichen der Benutzernavigation zu allen Fotos für einen bestimmten Monat.
  • Hinzufügen von Befehlen zu App-Leisten.

Hier ist das XAML für das Button-Steuerelement, mit dem Benutzer zu allen Fotos für einen bestimmten Monat navigieren können.

ImageBrowserView.xaml


<Button AutomationProperties.AutomationId="MonthGroupTitle"
        Content="{Binding Title}"
        Command="{Binding ElementName=MonthPhotosGridView, Path=DataContext.GroupCommand}"
        CommandParameter="{Binding}"
        Style="{StaticResource HiloTextButtonStyle}" />


Ein wichtiger Teil dieser Implementierung besteht darin, dass mit dem Command der Schaltfläche eine Bindung zur GroupCommand-Eigenschaft im Ansichtsmodell hergestellt wird. Darüber hinaus wird die Content-Eigenschaft der Schaltfläche an eine Textzeichenfolge gebunden. Sie können den Inhalt des Steuerelements jedoch an alle Klassen binden, die von Panel abgeleitet werden. Die Button wird mit dem HiloTextButtonStyle formatiert. Dabei wird das SubheaderTextStyle verwendet, das in der Datei "StandardStyles.xaml" angegeben ist; andere Darstellungselemente werden nicht verwendet.

Der ImageBrowserViewModel-Konstruktor legt den m_groupCommand (den ICommand-Sicherungswert für die GroupCommand-Eigenschaft) fest, sodass dieser auf die NavigateToGroup-Methode zeigt.

ImageBrowserViewModel.cpp


m_groupCommand = ref new DelegateCommand(ref new ExecuteDelegate(this, &ImageBrowserViewModel::NavigateToGroup), nullptr);


Die NavigateToGroup-Methode führt die Navigation zur Bildbrowserseite für den aktuellen Monat durch.

ImageBrowserViewModel.cpp


void ImageBrowserViewModel::NavigateToGroup(Object^ parameter)
{
    auto group = dynamic_cast<IPhotoGroup^>(parameter);
    assert(group != nullptr);
    if (group->Items->Size > 0)
    {
        auto photo = dynamic_cast<IPhoto^>(group->Items->GetAt(0));
        assert(photo != nullptr);
        
        create_task(photo->GetDateTakenAsync()).then([this, photo](DateTime dateTaken)
    {
        ImageNavigationData data(photo->Path, dateTaken);
        ViewModelBase::GoToPage(PageType::Image, data.SerializeToString());
    }).then(ObserveException<void>(m_exceptionPolicy));

    }
}


Weitere Informationen zum Binden von Befehlen für dieses Ansichtsmodell finden Sie unter Ausführen von Befehlen in einem Ansichtsmodell.

Weitere Informationen über Schaltfläche finden Sie unter Hinzufügen von Schaltflächen und Beispiel für wichtige XAML-Steuerelemente.

TextBlock

Mit dem TextBlock-Steuerelement wird Text angezeigt. Mithilfe von Textblöcken werden die Titel der einzelnen Seiten angezeigt, und das Popup-Steuerelement wird gefüllt. Dieses Steuerelement zeigt zusätzliche Informationen über ein Bild an, wenn der Benutzer auf das Bild drückt und es gedrückt hält.

Anzeigen von Fotoeigenschaften durch Drücken und Halten

Bindungen sowie der Einsatz von Ressourcen spielen beim Anzeigen von Text eine wichtige Rolle. Bindungen helfen, den Wert eines Textblocks bis zur Laufzeit zu verschieben (beispielsweise, um Informationen über ein Bild anzuzeigen). Ressourcen ermöglichen eine leichtere Lokalisierung Ihrer App. Weitere Informationen zur Lokalisierung finden Sie in diesem Leitfaden unter Vorbereiten der App für den weltweiten Markt.

Weitere Informationen über Textblöcken finden Sie unter Schnellstart: Anzeigen von Text und XAML-Beispiel für die Textanzeige.

AppBar

Das AppBar-Steuerelement ist eine Symbolleiste zum Anzeigen App-spezifischer Befehle. Hilo zeigt unten auf jeder Seite eine App-Leiste an. Außerdem wird auf der Bildbetrachtungsseite eine Navigationsleiste mit einem Bildstreifen für den aktuellen Monat angezeigt. Die untere App-Leiste kann mit der Page::BottomAppBar-Eigenschaft und die Navigationsleiste kann mit der Page::TopAppBar-Eigenschaft definiert werden.

Die Schaltflächen auf der unteren App-Leiste der Bildbetrachtungsseite werden wie folgt dargestellt.

Schaltflächen auf der unteren App-Leiste

Sie können einer Seite Schaltflächen für die Navigation oder wichtige Funktionen für eine App hinzufügen. Schaltflächen, die nicht für die Navigation oder die Verwendung der App benötigt werden, sollten auf einer App-Leiste platziert werden. Beispielsweise kann der Benutzer auf der Bildbrowserseite auf den Text eines bestimmten Monats klicken, um alle Fotos für diese Monat anzuzeigen. Nach unserem Dafürhalten wird die Navigation dadurch wesentlich erleichtert. Die Befehle zum Drehen und Zuschneiden sowie zur Anwendung eines Comic-Effekts wurden dagegen der App-Leiste hinzugefügt. Sie stellen sekundäre Befehle dar, und eine Ablenkung des Benutzers sollte vermieden werden.

Hier ist das XAML für die untere App-Leiste auf der Bildbetrachtungsseite. Diese App-Leiste enthält Button-Elemente, mit denen Benutzer einen Modus zum Drehen, Zuschneiden oder Anwenden von Comic-Effekten aufrufen können.

ImageView.xaml


<local:HiloPage.BottomAppBar>
    <AppBar x:Name="ImageViewBottomAppBar"
            x:Uid="AppBar"
            AutomationProperties.AutomationId="ImageViewBottomAppBar"
            Padding="10,0,10,0">
        <Grid>
            <StackPanel HorizontalAlignment="Left" 
                        Orientation="Horizontal">
                <Button x:Name="RotateButton"
                        x:Uid="RotateAppBarButton"
                        Command="{Binding RotateImageCommand}" 
                        Style="{StaticResource RotateAppBarButtonStyle}" 
                        Tag="Rotate" />
                <Button x:Name="CropButton"
                        x:Uid="CropAppBarButton"
                        Command="{Binding CropImageCommand}"
                        Style="{StaticResource CropAppBarButtonStyle}"
                        Tag="Crop" />
                <Button x:Name="CartoonizeButton"
                        x:Uid="CartoonizeAppBarButton"
                        Command="{Binding CartoonizeImageCommand}"
                        Style="{StaticResource CartoonEffectAppBarButtonStyle}"
                        Tag="Cartoon effect" />
                <Button x:Name="RotateButtonNoLabel"
                        Command="{Binding RotateImageCommand}" 
                        Style="{StaticResource RotateAppBarButtonNoLabelStyle}" 
                        Tag="Rotate"
                        Visibility="Collapsed">
                    <ToolTipService.ToolTip>
                        <ToolTip x:Uid="RotateAppBarButtonToolTip" />
                    </ToolTipService.ToolTip>
                </Button>
                <Button x:Name="CropButtonNoLabel"
                        Command="{Binding CropImageCommand}"
                        Style="{StaticResource CropAppBarButtonNoLabelStyle}"
                        Tag="Crop"
                        Visibility="Collapsed">
                    <ToolTipService.ToolTip>
                        <ToolTip x:Uid="CropAppBarButtonToolTip" />
                    </ToolTipService.ToolTip>
                </Button>
                <Button x:Name="CartoonizeButtonNoLabel"
                        Command="{Binding CartoonizeImageCommand}"
                        Style="{StaticResource CartoonEffectAppBarButtonNoLabelStyle}"
                        Tag="Cartoon effect"
                        Visibility="Collapsed">
                    <ToolTipService.ToolTip>
                        <ToolTip x:Uid="CartoonizeAppBarButtonToolTip" />
                    </ToolTipService.ToolTip>
                </Button>
            </StackPanel>
        </Grid>
    </AppBar>
</local:HiloPage.BottomAppBar>


Wir definieren zwei Arten von Schaltflächen: eine für das Querformat und eine für das Hochformat. Gemäß den Richtlinien für die Benutzeroberfläche von App-Leisten zeigen wird im Querformat Anzeigebeschriftungen für Schaltflächen an und blenden diese im Hochformat aus. Hier ist das XAML zum Definieren der Sichtbarkeit der Schaltflächen im Hochformat.

ImageView.xaml


<VisualState x:Name="FullScreenPortrait">
    <Storyboard>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackButton" 
                                       Storyboard.TargetProperty="Style">
            <DiscreteObjectKeyFrame KeyTime="0" 
                                    Value="{StaticResource PortraitBackButtonStyle}"/>
        </ObjectAnimationUsingKeyFrames>

        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemGridView"
                                       Storyboard.TargetProperty="ItemsPanel">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="{StaticResource HubVerticalVirtualizingStackPanelTemplate}" />
        </ObjectAnimationUsingKeyFrames>

        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemGridView" 
                                       Storyboard.TargetProperty="Padding">
            <DiscreteObjectKeyFrame KeyTime="0" 
                                    Value="96,0,10,56"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RotateButton"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="Collapsed"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CropButton"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="Collapsed"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CartoonizeButton"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="Collapsed"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RotateButtonNoLabel"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="Visible"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CropButtonNoLabel"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="Visible"/>
        </ObjectAnimationUsingKeyFrames>
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CartoonizeButtonNoLabel"
                                       Storyboard.TargetProperty="Visibility">
            <DiscreteObjectKeyFrame KeyTime="0"
                                    Value="Visible"/>
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</VisualState>


Tipp  Dieses XAML wurde manuell erstellt. Viele Entwickler bevorzugen dagegen Blend für Visual Studio zum Definieren visueller Zustände.

Weitere Informationen zur Verwendung von App-Leisten in Hilo finden Sie in diesem Leitfaden unter Vom Rand aus streifen: App-Befehle.

StackPanel

Das StackPanel-Steuerelement ordnet untergeordnete Elemente in einer Linie an, die senkrecht oder waagrecht ausgerichtet werden kann. Die Verwendung von StackPanel erstreckt sich auf folgende Bereiche:

  • Anordnen der Schaltflächen auf der App-Leiste.
  • Anzeigen eines Statusrings neben einem anderen Steuerelement wie Button.
  • Anzeigen von Elementen in einem Popup-Steuerelement, um die Funktion zum Drücken und Halten zu implementieren. Weitere Informationen finden Sie in diesem Leitfaden unter Gedrückt halten: Lernen.

Nachfolgend finden Sie ein Beispiel für das Anordnen von Schaltflächen auf der unteren App-Leiste der Hubseite mit StackPanel.

MainHubView.xaml


<local:HiloPage.BottomAppBar>
    <AppBar x:Name="MainHubViewBottomAppBar"
            x:Uid="AppBar"
            AutomationProperties.AutomationId="MainHubViewBottomAppBar"
            IsOpen="{Binding Path=IsAppBarOpen, Mode=TwoWay}"
            IsSticky="{Binding Path=IsAppBarSticky, Mode=TwoWay}"
            Padding="10,0,10,0"
            Visibility="{Binding Path=IsAppBarEnabled, Mode=TwoWay, Converter={StaticResource BoolToVisConverter}}">
        <Grid>
            <StackPanel HorizontalAlignment="Left" 
                        Orientation="Horizontal">
                <Button x:Name="RotateButton"
                        x:Uid="RotateAppBarButton"
                        Command="{Binding RotateImageCommand}" 
                        Style="{StaticResource RotateAppBarButtonStyle}" 
                        Tag="Rotate" />
                <Button x:Name="CropButton"
                        x:Uid="CropAppBarButton"
                        Command="{Binding CropImageCommand}"
                        Style="{StaticResource CropAppBarButtonStyle}"
                        Tag="Crop" />
                <Button x:Name="CartoonizeButton"
                        x:Uid="CartoonizeAppBarButton"
                        Command="{Binding CartoonizeImageCommand}"
                        Style="{StaticResource CartoonEffectAppBarButtonStyle}"
                        Tag="Cartoon effect" />
                <Button x:Name="RotateButtonNoLabel"
                        Command="{Binding RotateImageCommand}" 
                        Style="{StaticResource RotateAppBarButtonNoLabelStyle}" 
                        Tag="Rotate"
                        Visibility="Collapsed">
                    <ToolTipService.ToolTip>
                        <ToolTip x:Uid="RotateAppBarButtonToolTip" />
                    </ToolTipService.ToolTip>
                </Button>
                <Button x:Name="CropButtonNoLabel"
                        Command="{Binding CropImageCommand}"
                        Style="{StaticResource CropAppBarButtonNoLabelStyle}"
                        Tag="Crop"
                        Visibility="Collapsed">
                    <ToolTipService.ToolTip>
                        <ToolTip x:Uid="CropAppBarButtonToolTip" />
                    </ToolTipService.ToolTip>
                </Button>
                <Button x:Name="CartoonizeButtonNoLabel"
                        Command="{Binding CartoonizeImageCommand}"
                        Style="{StaticResource CartoonEffectAppBarButtonNoLabelStyle}"
                        Tag="Cartoon effect"
                        Visibility="Collapsed">
                    <ToolTipService.ToolTip>
                        <ToolTip x:Uid="CartoonizeAppBarButtonToolTip" />
                    </ToolTipService.ToolTip>
                </Button>
            </StackPanel>
        </Grid>
    </AppBar>
</local:HiloPage.BottomAppBar>


Wir legen die Orientation-Eigenschaft auf Horizontal fest, um die untergeordneten Elemente des StackPanel von links nach rechts anzuordnen. Legen Sie Orientation auf Vertical fest, um die untergeordneten Elemente von oben nach unten anzuordnen.

ListView

Mit dem ListView-Steuerelement wird Text vertikal angezeigt. Eine Möglichkeit, dieses Steuerelement zu verwenden, besteht im vertikalen Anzeigen von Fotos auf der Bildbetrachtungsseite, wenn sich die App im angedockten Modus befindet.

Vertikales Anzeigen von Daten mit ListView

Hier ist der XAML-Code für den ListView.

ImageView.xaml


<ListView x:Name="SnappedPhotosFilmStripListView"
          Grid.Row="1"
          AutomationProperties.AutomationId="SnappedPhotosFilmStripListView"
          Margin="0,-10,0,0"
          Padding="10,0,0,60"
          ItemsSource="{Binding Photos}" 
          IsItemClickEnabled="False"
          ItemContainerStyle="{StaticResource HiloListViewItemStyle}"
          SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
          SelectionMode="Single"
          Visibility="Collapsed">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Orientation="Vertical" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border>
                <Image Source="{Binding Path=Thumbnail}" 
                       Stretch="UniformToFill" />
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>


Diese ListView passt mithilfe von HiloListViewItemStyle (definiert in der Datei "ApplicationStyles.xaml") die Darstellung der ListViewItem-Instanzen an, die in der ListView angezeigt werden. Jedes ListViewItem stellt ein Image-Steuerelement dar, das in ein Border-Steuerelement eingeschlossen ist und in der DataTemplate des ListView definiert wird. Um die Virtualisierung der Benutzeroberfläche zu unterstützen, werden die ListViewItem-Instanzen mit einem (in der ItemsPanelTemplate des ListView definierten) VirtualizingStackPanel angezeigt. Weitere Informationen über die Virtualisierung der Benutzeroberfläche finden Sie in diesem Leitfaden unter Virtualisierung der Benutzeroberfläche beim Arbeiten mit umfangreicheren Datensätzen.

Beim Übergang der App in die angedockte Ansicht wird das Fotoraster mit dem Image-Steuerelement ausgeblendet, und die Fotos werden als vertikaler Bildstreifen angezeigt.

ImageView.xaml


<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PhotoGrid" 
                               Storyboard.TargetProperty="Visibility">
    <DiscreteObjectKeyFrame KeyTime="0" 
                            Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SnappedPhotosFilmStripListView" 
                               Storyboard.TargetProperty="Visibility">
    <DiscreteObjectKeyFrame KeyTime="0" 
                            Value="Visible"/>
</ObjectAnimationUsingKeyFrames>


Unserer Ansicht nach eignet sich das vertikale Layout von ListView sehr gut, um Gruppen von Fotos in der angedockten Ansicht anzuzeigen. (ListView ist mit GridView vergleichbar, da beide ListViewBase erben. Der Hauptunterschied zwischen beiden besteht in der Art und Weise, wie das Layout definiert wird.)

Weitere Informationen über ListView finden Sie unter Hinzufügen von ListView- und GridView-Steuerelementen, Beispiel für XAML-ListView- und -GridView-Steuerelemente und Beispiel für die Interaktivitätsanpassung von XAML-ListView- und -GridView-Steuerelementen.

SemanticZoom

Ein SemanticZoom-Steuerelement, ermöglicht dem Benutzer, zwischen zwei Ansichten einer Sammlung zu zoomen. Weitere Informationen zur Verwendung dieses Steuerelements für die Navigation zwischen großen Bildersammlungen finden Sie in diesem Leitfaden unter Zusammendrücken/Aufziehen: Zoom

Canvas und ContentControl

Das Canvas-Steuerelement unterstützt die absolute Positionierung untergeordneter Elemente relativ zur oberen linken Ecke des Canvas. Die Position des Rechtecks, das Sie zum Zuschneiden eines Fotos verwenden, wird mit Canvas gesteuert.

Tipp   Wenn keine absolute Positionierung erforderlich ist, können Sie auch ein dynamisches Layoutsteuerelement wie Grid verwenden. Ein dynamisches Layout passt sich automatisch an die jeweilige Bildschirmauflösung und -ausrichtung an. Feste Layoutsteuerelemente wie Canvas bieten mehr Kontrolle, müssen jedoch manuell angepasst werden, wenn sich Ausrichtung oder Layout der Seite ändern.

Hier ist der XAML-Code für den Canvas.

CropImageView.xaml


<Canvas x:Name="CropCanvas" HorizontalAlignment="Left" VerticalAlignment="Top">
    <ContentControl x:Name="CropOverlay"
                    Canvas.Left="{Binding CropOverlayLeft}"
                    Canvas.Top="{Binding CropOverlayTop}"
                    Height="{Binding CropOverlayHeight}"
                    MinHeight="100"
                    MinWidth="100"
                    Template="{StaticResource HiloCroppingOverlayTemplate}"
                    Visibility="{Binding Path=IsCropOverlayVisible, Converter={StaticResource BoolToVisConverter}}"
                    Width="{Binding CropOverlayWidth}">
        <Grid Background="Transparent"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Stretch"
              Tapped="OnCropRectangleTapped">
        </Grid>
    </ContentControl>
</Canvas>


Nachfolgend finden Sie eine Darstellung der Zuschneidefunktion von Hilo.

Zuschneidemodus in Hilo

Das Canvas-Steuerelement enthält ein untergeordnetes Element. Dieses ContentControl implementiert die Punkte, die Benutzer ziehen können, um die Grenzen des Rechtecks für den Zuschnitt anzupassen. Ein ContentControl ist ein Steuerelement mit einem Inhaltselement. Button erbt ebenso wie andere Standardsteuerelemente von ContentControl. Benutzerdefinierter Inhalt wird mit ContentControl definiert. Die ControlTemplateHiloCroppingOverlayTemplate wird im Abschnitt Resources der Datei "CropImageView.xaml" definiert. Diese ControlTemplate definiert ein Thumb-Element für jeden der 8 ziehbaren Punkte. HiloCroppingOverlayThumbStyle legt die Farbe und Form sowie weitere Stilelemente für einzelnen Punkte fest und wird in der Datei "ApplicationStyles.xaml" definiert.

CropImageView.xaml


<ControlTemplate x:Key="HiloCroppingOverlayTemplate" TargetType="ContentControl">
    <Grid>
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta"
               HorizontalAlignment="Stretch" 
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Top" />
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta" 
               HorizontalAlignment="Left"
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Stretch" />
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta"
               HorizontalAlignment="Right"
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Stretch" />
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta"
               HorizontalAlignment="Stretch"
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Bottom" />
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta"  
               HorizontalAlignment="Left"
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Top" />
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta" 
               HorizontalAlignment="Right"
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Top" />
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta" 
               HorizontalAlignment="Left"
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Bottom" />
        <Thumb Canvas.ZIndex="1"
               DragDelta="OnThumbDragDelta" 
               HorizontalAlignment="Right"
               Style="{StaticResource HiloCroppingOverlayThumbStyle}"
               VerticalAlignment="Bottom" />
        <ContentPresenter Content="{TemplateBinding ContentControl.Content}" />
    </Grid>
</ControlTemplate>


Weitere Informationen zum Zuschneiden von Elementen finden Sie in diesem Leitfaden unter Verwenden von Fingereingaben.

Popup

Mit dem Popup-Steuerelement werden zusätzliche Informationen über ein Bild angezeigt, wenn der Benutzer darauf drückt und das Bild gedrückt hält. Weitere Informationen zur Verwendung dieses Steuerelements finden Sie in diesem Leitfaden unter Gedrückt halten: Lernen.

[Nach oben]

Formatieren von Steuerelementen

Die Darstellung von Hilo wurde durch Formatieren und Anwenden von Vorlagen auf die Steuerelemente in der App angepasst.

Sie können mit Stilen die Steuerelementeigenschaften festlegen und dann für andere Steuerelemente übernehmen, um so für ein einheitliches Erscheinungsbild zu sorgen. Stile werden in XAML inline für ein Steuerelement oder als wiederverwendbare Ressource definiert. Ressourcen können in der XAML-Datei einer Seite, in der Datei "App.xaml" oder in einem separaten Ressourcenwörterbuch definiert werden. Ein Ressourcenwörterbuch kann App-übergreifend genutzt werden. Außerdem können in einer einzelnen App mehrere Ressourcenverzeichnisse zusammengeführt werden. Weitere Informationen finden Sie unter Schnellstart: Formatieren von Steuerelementen.

Sie können die Struktur und die Darstellung eines Steuerelements anpassen, indem Sie eine neue ControlTemplate für das Steuerelement definieren. Durch die Anwendung einer Vorlage auf ein Steuerelement entfällt oftmals die Notwendigkeit, benutzerdefinierte Steuerelemente zu erstellen. Weitere Informationen finden Sie unter Schnellstart: Steuerelementvorlagen.

[Nach oben]

Virtualisierung der Benutzeroberfläche beim Arbeiten mit umfangreicheren Datensätzen

Da es sich bei Hilo um eine Foto-App handelt, müssen wir uns überlegen, wie die Fotos des Benutzer am besten geladen und angezeigt werden können. Wir wissen, dass die Anzahl der in einem Monat aufgenommenen Fotos von einigen wenigen bis zu vielen hundert stark schwanken kann. Für beide Fälle soll eine möglichst optimale UX erreicht werden.

Ferner soll der Speicherbedarf der App so gering wie möglich gehalten werden. Die Wahrscheinlichkeit, dass eine App angehalten wird oder nicht mehr reagiert und dann beendet wird, steigt mit zunehmendem Speicherbedarf.

Da jeweils immer nur eine bestimmte Anzahl an Fotos angezeigt werden kann, machen wir uns die Virtualisierung der Benutzeroberfläche zunutze. Die Virtualisierung der Benutzeroberfläche ermöglicht es Steuerelementen, die von ItemsControl abgeleitet werden (d. h. Steuerelemente, mit denen eine Sammlung von Elementen dargestellt werden kann), nur die Elemente der Benutzeroberfläche in den Arbeitsspeicher zu laden, die sich in der Nähe des Viewports oder des sichtbaren Bereich des Steuerelements befinden. Während der Benutzer durch die Liste blättert, werden Elemente, die sich zuvor in der Nähe des Viewports befanden, aus dem Speicher entfernt, und neue Elemente werden in den Speicher geladen.

Steuerelemente wie ListView und GridView, die von ItemsControl abgeleitet werden, führen standardmäßig eine Virtualisierung der Benutzeroberfläche durch. XAML generiert die Benutzeroberfläche für das Element und hält sie im Speicher vor, solange sich das Element in der Nähe des angezeigten Bereichs auf dem Bildschirm befindet. Wenn das Element nicht mehr angezeigt wird, nutzt das Element den Arbeitsspeicher für ein anderes Element, das sich in der Nähe des angezeigten Bereichs auf dem Bildschirm befindet.

Wenn Sie ein ItemsControl neu gestalten, um ein anderes Panel als das Standardpanel zu verwenden, unterstützt das Steuerelement weiterhin die Virtualisierung der Benutzeroberfläche, solange ein Virtualisierungspanel verwendet wird. Zu den standardmäßigen Virtualisierungspanels zählen WrapGrid und VirtualizingStackPanel. Bei Verwendung von Standardpanels ohne Virtualisierung wie VariableSizedWrapGrid und StackPanel wird die Virtualisierung der Benutzeroberfläche für das Steuerelement beendet.

Hinweis  Für gruppierte Daten wird die UI-Virtualisierung nicht unterstützt. In Hilo wird die Größe von Gruppen daher begrenzt, um den Speicherbedarf der App so gering wie möglich zu halten.

Tipp  Sie können auch den semantischen Zoom verwenden, um die Effizienz im Umgang mit größeren Datensätzen zu steigern. Weitere Informationen zur Verwendung des semantischen Zooms in Hilo finden Sie unter Zusammendrücken/Aufziehen: Zoom.

Weitere Informationen über den Umgang mit großen Datensätzen finden Sie unter Verwenden der Virtualisierung mit einer Liste oder einem Raster und Effizientes Laden, Speichern und Anzeigen großer Datenmengen. Informationen zu den Leistungsaspekten in Hilo finden Sie unter Leistungsoptimierung.

[Nach oben]

Überschreiben von integrierten Steuerelementen

Unser Ziel war es, dass das erste Bild auf der Hubseite den Abmessungen von vier Miniaturbildern entspricht und die übrigen Miniaturbilder die normale Breite und Höhe aufweisen.

Benutzerdefinierter Layoutstil

Diese Art von Layout nur mithilfe von Stilen zu definieren (d. h. das erste Element in einer Sammlung zu erkennen und ordnungsgemäß zu formatieren), kann eine Herausforderung darstellen Wir haben uns für eine andere Herangehensweise entschieden, und die VariableGridView-Klasse definiert, die von GridView abgeleitet wird.

VariableGridView.h


[Windows::Foundation::Metadata::WebHostHidden]
public ref class VariableGridView sealed : public Windows::UI::Xaml::Controls::GridView
{
protected:
    virtual void PrepareContainerForItemOverride(Windows::UI::Xaml::DependencyObject^ element, Platform::Object^ item) override;
};


Damit das erste Bild mehrere Zeilen und Spalten umfassen kann, haben wir die PrepareContainerForItemOverride-Methode überschrieben.

VariableGridView.cpp


void VariableGridView::PrepareContainerForItemOverride(DependencyObject^ element, Object^ item)
{
    auto model = dynamic_cast<IResizable^>(item);

    if (model != nullptr)
    {
        element->SetValue(VariableSizedWrapGrid::ColumnSpanProperty, model->ColumnSpan);
        element->SetValue(VariableSizedWrapGrid::RowSpanProperty, model->RowSpan);
    }

    GridView::PrepareContainerForItemOverride(element, item);
}


Um den Zeilen- und Spaltenumfang im Rahmen der Implementierung im übergeordneten Container definieren zu können, wurden die IResizable-Schnittstelle definiert.

IResizable.h


public interface class IResizable
{
    property int ColumnSpan 
    {
        int get();
        void set(int value);
    }

    property int RowSpan
    {
        int get();
        void set(int value);
    }
};


Die Photo-Klasse implementiert sowohl IPhoto als auch IResizable. Der Konstruktor legt den Standardwert für den Zeilen- und den Spaltenumfang jeweils auf 1 fest.

Photo.h


[Windows::UI::Xaml::Data::Bindable]
[Windows::Foundation::Metadata::WebHostHidden]
public ref class Photo sealed : public IResizable, public IPhoto, public Windows::UI::Xaml::Data::INotifyPropertyChanged


Die HubPhotoGroup::QueryPhotosAsync-Methode ist für das Laden von Fotos für die Hubseite verantwortlich. Sie legt die Werte für den Zeilen- und Spaltenumfang des ersten Fotos in der Sammlung auf 2 fest.

HubPhotoGroup.cpp


bool firstPhoto = true;
for (auto photo : photos)
{
    if (firstPhoto)
    {
        IResizable^ resizable = dynamic_cast<IResizable^>(photo);
        if (nullptr != resizable)
        {
            resizable->ColumnSpan = 2;
            resizable->RowSpan = 2;
        }
        firstPhoto = false;
    }
    m_photos->Append(photo);
}


Das erste Foto in der Hubansicht umfasst nun zwei Zeilen und zwei Spalten.

Hinweis  In dieser Lösung kontrolliert das Modell die Ansicht sowie das zugehörige Layout. Dies widerspricht dem MVVM-Muster (siehe Verwenden des MVVM-Musters). Wir haben jedoch versucht, diese Lösung aus Gründen der Flexibilität nach Möglichkeit zu abstrahieren. Die Lösung betrifft ein Problem, das relativ wenig Spielraum lässt. Aus diesem Grund erschien uns das Abwägen zwischen einer funktionierenden App und der Einführung eines bestimmten Kopplungsgrads zwischen der Ansicht und dem Modell akzeptabel.

[Nach oben]

Fingereingaben und Gesten

Die XAML-Laufzeit weist eine integrierte Unterstützung für Fingereingaben auf. Die XAML-Laufzeit verwendet für zahlreiche Interaktionen ein gängiges Ereignissystem. Sie können daher automatische Unterstützung für Maus-, Stift- und andere zeigerbasierte Eingaben abrufen.

Tipp  Entwerfen Sie Ihre App für Fingereingaben. Die Unterstützung von Maus- und Stifteingaben gibt es kostenlos dazu.

Weitere Informationen über die Verwendung von Fingereingaben in Hilo finden Sie unter Verwenden von Fingereingaben.

[Nach oben]

Testen von Steuerelementen

Achten Sie beim Testen Ihrer App darauf, dass die einzelnen Steuerelemente in unterschiedlichen Konfigurationen und Ausrichtungen das gewünschte Verhalten aufweisen. Beim Verwenden eines Steuerelements zum Hinzufügen einer neuen Funktion zur App wurde sichergestellt, dass das Steuerelement in angedockten und gefüllten Ansichten sowie sowohl im Querformat als auch im Hochformat das richtige Verhalten aufweist.

Wenn Ihr Monitor keine Fingereingaben unterstützt, können Sie mithilfe des Simulators das Zusammenziehen und Auseinanderrücken, das Zoomen, das Drehen und andere Gesten emulieren. Darüber hinaus können Sie die Geolocation und das Arbeiten mit unterschiedlichen Bildschirmauflösungen simulieren. Weitere Informationen finden Sie unter Ausführen von Windows Store-Apps im Simulator.

Sie können Ihre App auf einem Computer testen, der nicht über Visual Studio, aber über die erforderliche Hardware verfügt. Weitere Informationen finden Sie unter Ausführen von Windows Store-Apps auf einem Remotecomputer.

Weitere Informationen zum Testen von Hilo finden Sie unter Testen von Apps.

[Nach oben]

 

 

Anzeigen:
© 2014 Microsoft