Dela via


Binda hierarkiska data och skapa en huvud-/informationsvy med Windows App SDK

Anmärkning

Se även UWP-exemplet master/detail.

Du kan skapa en huvud-/informationsvy på flera nivåer (kallas även listinformation) för hierarkiska data genom att binda objektkontroller till CollectionViewSource instanser som är sammanbundna i en kedja. I det här avsnittet använder vi {x:Bind}-markeringstillägget där det är möjligt, och det mer flexibla (men mindre högpresterande) {Binding}-markeringstillägget om det behövs.

En vanlig struktur för Windows App SDK-appar är att navigera till olika informationssidor när en användare gör ett val i en huvudlista. Detta är användbart när du vill tillhandahålla en omfattande visuell representation av varje objekt på varje nivå i en hierarki. Ett annat alternativ är att visa flera datanivåer på en enda sida. Detta är användbart när du vill visa några enkla listor som gör att användaren snabbt kan öka detaljnivån till ett objekt av intresse. I det här avsnittet beskrivs hur du implementerar den här interaktionen. Instanserna CollectionViewSource håller reda på den aktuella markeringen på varje nivå i hierarkin.

Vi skapar en vy över en sportlagshierarki som är organiserad i listor för ligor, divisioner och lag och innehåller en gruppinformationsvy. När du väljer ett objekt från en lista uppdateras efterföljande vyer automatiskt.

huvud-/informationsvy för en sporthierarki

Förutsättningar

Det här avsnittet förutsätter att du vet hur du skapar en grundläggande Windows App SDK-app. Anvisningar om hur du skapar din första Windows App SDK-app finns i Skapa ditt första WinUI 3-projekt (Windows App SDK).

Skapa projektet

Skapa en ny tom app, paketerad (WinUI 3 i Desktop) projekt. Ge den namnet "MasterDetailsBinding".

Skapa datamodellen

Lägg till en ny klass i projektet, ge det namnet ViewModel.cs och lägg till den här koden i det. Det här är din bindningskällaklass.

using System.Collections.Generic;
using System.Linq;

namespace MasterDetailsBinding
{
    public class Team
    {
        public string Name { get; set; }
        public int Wins { get; set; }
        public int Losses { get; set; }
    }

    public class Division
    {
        public string Name { get; set; }
        public IEnumerable<Team> Teams { get; set; }
    }

    public class League
    {
        public string Name { get; set; }
        public IEnumerable<Division> Divisions { get; set; }
    }

    public class LeagueList : List<League>
    {
        public LeagueList()
        {
            AddRange(GetLeague().ToList());
        }

        public IEnumerable<League> GetLeague()
        {
            return from x in Enumerable.Range(1, 2)
                   select new League
                   {
                       Name = "League " + x,
                       Divisions = GetDivisions(x).ToList()
                   };
        }

        public IEnumerable<Division> GetDivisions(int x)
        {
            return from y in Enumerable.Range(1, 3)
                   select new Division
                   {
                       Name = string.Format("Division {0}-{1}", x, y),
                       Teams = GetTeams(x, y).ToList()
                   };
        }

        public IEnumerable<Team> GetTeams(int x, int y)
        {
            return from z in Enumerable.Range(1, 4)
                   select new Team
                   {
                       Name = string.Format("Team {0}-{1}-{2}", x, y, z),
                       Wins = 25 - (x * y * z),
                       Losses = x * y * z
                   };
        }
    }
}

Skapa vyn

Exponera sedan bindningskällans klass från klassen som representerar din sida med kod. Det gör vi genom att lägga till en egenskap av typen LeagueList i MainWindow.

namespace MasterDetailsBinding
{
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ViewModel = new LeagueList();
        }
        public LeagueList ViewModel { get; set; }
    }
}

Ersätt slutligen innehållet i Filen MainWindow.xaml med följande markering, som deklarerar tre CollectionViewSource-instanser och binder dem samman i en kedja. De följande kontrollerna kan sedan binda till den lämpliga CollectionViewSource, beroende på dess nivå i hierarkin.

<Window
    x:Class="MasterDetailsBinding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MasterDetailsBinding"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Grid.Resources>
            <CollectionViewSource x:Name="Leagues"
                Source="{x:Bind ViewModel}"/>
            <CollectionViewSource x:Name="Divisions"
                Source="{Binding Divisions, Source={StaticResource Leagues}}"/>
            <CollectionViewSource x:Name="Teams"
                Source="{Binding Teams, Source={StaticResource Divisions}}"/>
    
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="15"/>
                <Setter Property="FontWeight" Value="Bold"/>
            </Style>
            <Style TargetType="ListBox">
                <Setter Property="FontSize" Value="15"/>
            </Style>
            <Style TargetType="ContentControl">
                <Setter Property="FontSize" Value="15"/>
            </Style>
        </Grid.Resources>

        <StackPanel Orientation="Horizontal">

            <!-- All Leagues view -->
            <StackPanel Margin="5">
                <TextBlock Text="All Leagues"/>
                <ListBox ItemsSource="{Binding Source={StaticResource Leagues}}" 
                         DisplayMemberPath="Name"/>
            </StackPanel>

            <!-- League/Divisions view -->
            <StackPanel Margin="5">
                <TextBlock Text="{Binding Name, Source={StaticResource Leagues}}"/>
                <ListBox ItemsSource="{Binding Source={StaticResource Divisions}}" 
                         DisplayMemberPath="Name"/>
            </StackPanel>

            <!-- Division/Teams view -->
            <StackPanel Margin="5">
                <TextBlock Text="{Binding Name, Source={StaticResource Divisions}}"/>
                <ListBox ItemsSource="{Binding Source={StaticResource Teams}}" 
                         DisplayMemberPath="Name"/>
            </StackPanel>

            <!-- Team view -->
            <ContentControl Content="{Binding Source={StaticResource Teams}}">
                <ContentControl.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Margin="5">
                            <TextBlock Text="{Binding Name}" 
                                       FontSize="15" FontWeight="Bold"/>
                            <StackPanel Orientation="Horizontal" Margin="10,10">
                                <TextBlock Text="Wins:" Margin="0,0,5,0"/>
                                <TextBlock Text="{Binding Wins}"/>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal" Margin="10,0">
                                <TextBlock Text="Losses:" Margin="0,0,5,0"/>
                                <TextBlock Text="{Binding Losses}"/>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ContentControl.ContentTemplate>
            </ContentControl>
        </StackPanel>
    </Grid>
</Window>

Observera att genom att binda direkt till CollectionViewSourceantyder du att du vill binda till det aktuella objektet i bindningar där sökvägen inte kan hittas i själva samlingen. Du behöver inte ange egenskapen CurrentItem som sökväg för bindningen, även om du kan göra det om det finns tvetydigheter. Till exempel har ContentControl- som representerar teamvyn sin egenskap Content som är bunden till TeamsCollectionViewSource. Kontrollerna i DataTemplate binder dock till egenskaperna för klassen Team, eftersom CollectionViewSource automatiskt tillhandahåller det för närvarande valda teamet från teamlistan när det behövs.

Se även