Partilhar via


Vincular dados hierárquicos e criar uma exibição mestre/detalhes com WinUI

Saiba como criar uma vista mestre/detalhes de múltiplos níveis de dados hierárquicos no WinUI ao vincular controlos de itens a instâncias CollectionViewSource. Este artigo explica como usar a extensão de marcação {x:Bind} para obter melhor desempenho e a extensão de marcação {Binding} quando a flexibilidade é necessária.

Uma estrutura comum para aplicativos WinUI é navegar para páginas de detalhes diferentes quando um usuário faz uma seleção em uma lista mestra. Essa estrutura é útil quando você deseja fornecer uma representação visual rica de cada item em todos os níveis de uma hierarquia. Outra opção é exibir vários níveis de dados em uma única página. Essa estrutura é útil quando você deseja exibir algumas listas simples que permitem ao usuário detalhar rapidamente um item de interesse. Este artigo descreve como implementar essa interação. As instâncias CollectionViewSource controlam a seleção atual em cada nível hierárquico.

Você cria uma exibição de uma hierarquia de equipe esportiva que é organizada em listas para ligas, divisões e equipes, e inclui uma exibição de detalhes da equipe. Quando você seleciona um item de qualquer lista, os modos de exibição subsequentes são atualizados automaticamente.

Captura de ecrã de uma vista mestre/detalhes de uma hierarquia desportiva. A visão inclui ligas, divisões e equipes.

Sugestão

Consulte também o exemplo de UWP Master/detail.

Pré-requisitos

Este artigo pressupõe que você saiba como criar um aplicativo WinUI básico. Para obter instruções sobre como criar seu primeiro aplicativo WinUI, consulte Criar um aplicativo WinUI.

Criar o projeto

Crie um novo projeto de aplicação em branco, empacotado (WinUI 3 para ambiente de trabalho). Dê-lhe o nome de "MasterDetailsBinding".

Criar o modelo de dados

Adicione uma nova classe ao seu projeto, nomeie-a ViewModel.cse adicione esse código a ela. Esta classe é sua classe de origem de ligação.

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

Criar a visualização

Em seguida, exponha a classe de origem de vinculação da classe que representa sua página de marcação. Adicione uma propriedade do tipo LeagueList a MainWindow.

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

Finalmente, substitua o conteúdo do arquivo MainWindow.xaml pela marcação a seguir. Essa marcação declara três instâncias CollectionViewSource e as une em uma cadeia. Os controlos subsequentes podem então associar-se ao CollectionViewSourceadequado, dependendo do seu nível na hierarquia.

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

Ao vincular diretamente ao CollectionViewSource, você implica que deseja vincular ao item atual em associações onde o caminho não pode ser encontrado na própria coleção. Você não precisa especificar a CurrentItem propriedade como o caminho para a associação, embora possa adicioná-la se houver alguma ambiguidade. Por exemplo, o ContentControl, que representa a vista da equipa, tem a sua propriedade Content vinculada ao TeamsCollectionViewSource. No entanto, os controlos no DataTemplate se associam às propriedades da classe Team porque o CollectionViewSource fornece a equipa atualmente selecionada da lista de equipas automaticamente, quando necessário.

Ver também