Share via


Erstellen eines Xamarin.Forms-DataTemplate-Objekts

Datenvorlagen können inline erstellt werden, z. B. in einem ResourceDictionary-Objekt oder über einen benutzerdefinierten Typ oder geeigneten Xamarin.Forms-Zellentyp. In diesem Artikel werden alle Methoden erläutert.

Ein gängiges Verwendungsszenario für eine DataTemplate ist das Anzeigen von Daten aus einer Objektsammlung in einer ListView. Das Aussehen der Daten in jeder Zelle in der ListView kann durch das Festlegen der ListView.ItemTemplate-Eigenschaft auf DataTemplate definiert werden. Dafür gibt es mehrere Möglichkeiten:

Unabhängig von der verwendeten Methode führt dies dazu, dass das Aussehen jeder Zelle in der ListView von einer DataTemplate definiert wird. Dies wird im folgenden Screenshots veranschaulicht:

ListView mit einem DataTemplate-Objekt

Erstellen eines Inline-DataTemplate-Objekts

Die ListView.ItemTemplate-Eigenschaft kann auf eine Inline-DataTemplate festgelegt werden. Eine Inlinevorlage wird als direktes untergeordnetes Element einer entsprechenden Steuerelementeigenschaft eingefügt. Sie sollte verwendet werden, wenn die Datenvorlage nicht an einer anderen Stelle wiederverwendet werden muss. Die in der DataTemplate angegebenen Elemente definieren das Aussehen jeder Zelle. Dies wird in folgendem XAML-Codebeispiel veranschaulicht:

<ListView Margin="0,20,0,0">
    <ListView.ItemsSource>
        <x:Array Type="{x:Type local:Person}">
            <local:Person Name="Steve" Age="21" Location="USA" />
            <local:Person Name="John" Age="37" Location="USA" />
            <local:Person Name="Tom" Age="42" Location="UK" />
            <local:Person Name="Lucas" Age="29" Location="Germany" />
            <local:Person Name="Tariq" Age="39" Location="UK" />
            <local:Person Name="Jane" Age="30" Location="USA" />
        </x:Array>
    </ListView.ItemsSource>
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <Grid>
                    ...
                    <Label Text="{Binding Name}" FontAttributes="Bold" />
                    <Label Grid.Column="1" Text="{Binding Age}" />
                    <Label Grid.Column="2" Text="{Binding Location}" HorizontalTextAlignment="End" />
                </Grid>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Das untergeordnete Element einer Inline-DataTemplate muss den Typ Cell aufweisen oder von diesem abgeleitet sein. In diesem Beispiel wird ViewCell verwendet, das sich aus Cell ableitet. Das Layout in der ViewCell wird hier von einem Grid-Objekt bestimmt. Das Grid-Objekt enthält drei Label-Instanzen, die ihre Text-Eigenschaften an die entsprechenden Eigenschaften jedes Person-Objekts in der Sammlung binden.

Der äquivalente C#-Code ist im folgenden Codebeispiel zu sehen:

public class WithDataTemplatePageCS : ContentPage
{
    public WithDataTemplatePageCS()
    {
        ...
        var people = new List<Person>
        {
            new Person { Name = "Steve", Age = 21, Location = "USA" },
            ...
        };

        var personDataTemplate = new DataTemplate(() =>
        {
            var grid = new Grid();
            ...
            var nameLabel = new Label { FontAttributes = FontAttributes.Bold };
            var ageLabel = new Label();
            var locationLabel = new Label { HorizontalTextAlignment = TextAlignment.End };

            nameLabel.SetBinding(Label.TextProperty, "Name");
            ageLabel.SetBinding(Label.TextProperty, "Age");
            locationLabel.SetBinding(Label.TextProperty, "Location");

            grid.Children.Add(nameLabel);
            grid.Children.Add(ageLabel, 1, 0);
            grid.Children.Add(locationLabel, 2, 0);

            return new ViewCell { View = grid };
        });

        Content = new StackLayout
        {
            Margin = new Thickness(20),
            Children = {
                ...
                new ListView { ItemsSource = people, ItemTemplate = personDataTemplate, Margin = new Thickness(0, 20, 0, 0) }
            }
        };
    }
}

In C# wird die Inline-DataTemplate mit einer Konstruktorüberladung erstellt, die ein Func-Argument angibt.

Erstellen eines DataTemplate-Objekts mit einem Typ

Die ListView.ItemTemplate-Eigenschaft kann auch als DataTemplate festgelegt werden, die über einen Zellentyp erstellt wird. Ein Vorteil dieser Vorgehensweise besteht darin, dass das vom Zellentyp definierte Aussehen von weiteren Datenvorlagen in der Anwendung wiederverwendet werden kann. Der folgende XAML Code ist ein Beispiel für ein solches Vorgehen:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DataTemplates"
             ...>
    <StackLayout Margin="20">
        ...
        <ListView Margin="0,20,0,0">
           <ListView.ItemsSource>
                <x:Array Type="{x:Type local:Person}">
                    <local:Person Name="Steve" Age="21" Location="USA" />
                    ...
                </x:Array>
            </ListView.ItemsSource>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <local:PersonCell />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

Hier wird die ListView.ItemTemplate-Eigenschaft auf DataTemplate festgelegt, die über einen benutzerdefinierten Typ erstellt wird, der das Aussehen der Zelle definiert. Der benutzerdefinierte Typ muss von einem ViewCell-Typ abgeleitet werden. Dies wird im folgenden Codebeispiel veranschaulicht:

<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          x:Class="DataTemplates.PersonCell">
     <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.5*" />
            <ColumnDefinition Width="0.2*" />
            <ColumnDefinition Width="0.3*" />
        </Grid.ColumnDefinitions>
        <Label Text="{Binding Name}" FontAttributes="Bold" />
        <Label Grid.Column="1" Text="{Binding Age}" />
        <Label Grid.Column="2" Text="{Binding Location}" HorizontalTextAlignment="End" />
    </Grid>
</ViewCell>

In der ViewCell wird hier das Layout von einem Grid-Objekt bestimmt. Das Grid-Objekt enthält drei Label-Instanzen, die ihre Text-Eigenschaften an die entsprechenden Eigenschaften jedes Person-Objekts in der Sammlung binden.

Der entsprechende C#-Code ist im folgenden Codebeispiel zu sehen:

public class WithDataTemplatePageFromTypeCS : ContentPage
{
    public WithDataTemplatePageFromTypeCS()
    {
        ...
        var people = new List<Person>
        {
            new Person { Name = "Steve", Age = 21, Location = "USA" },
            ...
        };

        Content = new StackLayout
        {
            Margin = new Thickness(20),
            Children = {
                ...
                new ListView { ItemTemplate = new DataTemplate(typeof(PersonCellCS)), ItemsSource = people, Margin = new Thickness(0, 20, 0, 0) }
            }
        };
    }
}

In C# wird die Inline-DataTemplate mit einer Konstruktorüberladung erstellt, die den Zellentyp als Argument angibt. Der Zellentyp muss vom ViewCell-Typ abgeleitet werden. Dies wird im folgenden Codebeispiel veranschaulicht:

public class PersonCellCS : ViewCell
{
    public PersonCellCS()
    {
        var grid = new Grid();
        ...
        var nameLabel = new Label { FontAttributes = FontAttributes.Bold };
        var ageLabel = new Label();
        var locationLabel = new Label { HorizontalTextAlignment = TextAlignment.End };

        nameLabel.SetBinding(Label.TextProperty, "Name");
        ageLabel.SetBinding(Label.TextProperty, "Age");
        locationLabel.SetBinding(Label.TextProperty, "Location");

        grid.Children.Add(nameLabel);
        grid.Children.Add(ageLabel, 1, 0);
        grid.Children.Add(locationLabel, 2, 0);

        View = grid;
    }
}

Hinweis

Beachten Sie, dass Xamarin.Forms außerdem Zellentypen beinhaltet, die verwendet werden können, um einfache Daten in ListView-Zellen anzuzeigen. Weitere Informationen finden Sie im Artikel zur Darstellung von Zellen.

Erstellen eines DataTemplate-Objekts als Ressource

Datenvorlage können auch als wiederverwendbare Objekte in einem ResourceDictionary erstellt werden. Geben Sie dazu jeder Deklaration ein eindeutiges x:Key-Attribut, das sie mit einem aussagekräftigen Schlüssel im ResourceDictionary versieht. Dies wird in folgendem XAML-Codebeispiel veranschaulicht:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             ...>
    <ContentPage.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="personTemplate">
                 <ViewCell>
                    <Grid>
                        ...
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout Margin="20">
        ...
        <ListView ItemTemplate="{StaticResource personTemplate}" Margin="0,20,0,0">
            <ListView.ItemsSource>
                <x:Array Type="{x:Type local:Person}">
                    <local:Person Name="Steve" Age="21" Location="USA" />
                    ...
                </x:Array>
            </ListView.ItemsSource>
        </ListView>
    </StackLayout>
</ContentPage>

Das DataTemplate wird der ListView.ItemTemplate-Eigenschaft mithilfe der Markuperweiterung StaticResource zugewiesen. Beachten Sie, dass das DataTemplate-Objekt zwar im ResourceDictionary-Objekt der Seite definiert wird, es aber dennoch auch auf Steuerelementebene oder Anwendungsebene definiert werden kann.

Im folgenden Codebeispiel wird die entsprechende Seite in C# dargestellt:

public class WithDataTemplatePageCS : ContentPage
{
  public WithDataTemplatePageCS ()
  {
    ...
    var personDataTemplate = new DataTemplate (() => {
      var grid = new Grid ();
      ...
      return new ViewCell { View = grid };
    });

    Resources = new ResourceDictionary ();
    Resources.Add ("personTemplate", personDataTemplate);

    Content = new StackLayout {
      Margin = new Thickness(20),
      Children = {
        ...
        new ListView { ItemTemplate = (DataTemplate)Resources ["personTemplate"], ItemsSource = people };
      }
    };
  }
}

Das DataTemplate-Objekt wird dem ResourceDictionary-Objekt mithilfe der Add-Methode hinzugefügt, die eine Key-Zeichenfolge angibt, mit der auf die DataTemplate verwiesen wird, wenn diese abgerufen wird.

Zusammenfassung

In diesem Artikel wurde beschrieben, wie Sie Datenvorlagen auf unterschiedliche Weisen erstellen können: inline, über einen benutzerdefinierten Typ oder in einem ResourceDictionary-Objekt. Eine Inlinevorlage sollte verwendet werden, wenn keine Notwendigkeit besteht, die Datenvorlage woanders erneut zu verwenden. Alternativ kann eine Datenvorlage erneut verwendet werden, indem sie als benutzerdefinierter Typ oder als Ressource auf Steuerelementebene, Seitenebene oder Anwendungsebene definiert wird.