Compartir a través de


Enlazar datos jerárquicos y crear una vista maestro-detalle

Nota Vea también elde ejemplo maestro/detalle de .

Puede crear una vista maestra/detalles de varios niveles (también conocida como lista-detalles) de datos jerárquicos enlazando controles de elementos a instancias de CollectionViewSource que están conectadas en cadena. En este tema usamos la extensión de marcado {x:Bind} de siempre que sea posible, y la extensión de marcado {Binding} más flexible (pero menos eficaz) extensión de marcado {Binding} cuando sea necesario.

Una estructura común para las aplicaciones para la Plataforma universal de Windows (UWP) es navegar a diferentes páginas de detalles cuando un usuario realiza una selección en una lista maestra. Esto resulta útil cuando desea proporcionar una representación visual enriquecida de cada elemento en cada nivel de una jerarquía. Otra opción es mostrar varios niveles de datos en una sola página. Esto resulta útil cuando desea mostrar algunas listas sencillas que permiten al usuario explorar en profundidad rápidamente un elemento de interés. En este tema se describe cómo implementar esta interacción. Las instancias de CollectionViewSource realizan un seguimiento de la selección actual en cada nivel jerárquico.

Crearemos una vista de una jerarquía de equipos deportivos que se organiza en listas para ligas, divisiones y equipos, e incluye una vista de detalles del equipo. Al seleccionar un elemento de cualquier lista, las vistas posteriores se actualizan automáticamente.

vista principal/detalles de una jerarquía deportiva

Prerrequisitos

En este tema se supone que sabes cómo crear una aplicación básica para UWP. Para obtener instrucciones sobre cómo crear tu primera aplicación para UWP, consulta Crear tu primera aplicación para UWP con C# o Visual Basic.

Creación del proyecto

Cree un nuevo proyecto Aplicación vacía (Windows Universal). Asígneles el nombre "MasterDetailsBinding".

Creación del modelo de datos

Agregue una nueva clase al proyecto, asígnele el nombre ViewModel.cs y agréguele este código. Esta será tu clase de origen de vinculación.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

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()
        {
            this.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
                   };
        }
    }
}

Crea la vista

A continuación, exponga la clase de origen de la vinculación desde la clase que representa su página de marcado. Para ello, agregamos una propiedad de tipo LeagueList a MainPage.

namespace MasterDetailsBinding
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.ViewModel = new LeagueList();
        }
        public LeagueList ViewModel { get; set; }
    }
}

Por último, reemplace el contenido del archivo MainPage.xaml por el marcado siguiente, que declara tres instancias collectionViewSource y las enlaza en una cadena. A continuación, los controles posteriores se pueden enlazar al CollectionViewSource adecuado, en función de su nivel en la jerarquía.

<Page
    x:Class="MasterDetailsBinding.MainPage"
    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">

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

    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

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

Tenga en cuenta que, si enlaza directamente con el CollectionViewSource, está indicando que quiere vincularse con el elemento actual en las vinculaciones donde no se puede encontrar la ruta en la propia colección. No es necesario especificar la propiedad CurrentItem como la ruta de acceso para la vinculación, aunque es posible hacerlo si hay alguna ambigüedad. Por ejemplo, el ContentControl que representa la vista del equipo tiene su propiedad Content enlazada a la TeamsCollectionViewSource. Sin embargo, los controles en el DataTemplate se enlazan a las propiedades de la clase Team porque el CollectionViewSource proporciona automáticamente el equipo actualmente seleccionado de la lista de equipos cuando es necesario.