CollectionViewSource 인스턴스에 항목 컨트롤을 바인딩하여 WinUI에서 계층적 데이터의 다단계 마스터/세부 정보 보기를 만드는 방법을 알아봅니다. 이 문서에서는 향상된 성능을 위해 {x:Bind} 태그 확장을 사용하고 유연성이 필요한 경우 {Binding} 태그 확장을 사용하는 방법을 설명합니다.
WinUI 앱의 일반적인 구조 중 하나는 사용자가 마스터 목록에서 선택할 때 다른 세부 정보 페이지로 이동하는 것입니다. 이 구조는 계층 구조의 모든 수준에서 각 항목의 풍부한 시각적 표현을 제공하려는 경우에 유용합니다. 또 다른 옵션은 단일 페이지에 다단계로 된 데이터를 표시하는 것입니다. 이 구조는 사용자가 관심 있는 항목으로 신속하게 드릴다운할 수 있는 몇 가지 간단한 목록을 표시하려는 경우에 유용합니다. 이 문서에서는 이 상호 작용을 구현하는 방법을 설명합니다. CollectionViewSource 인스턴스는 각 계층 수준에서 현재 선택 영역을 추적합니다.
리그, 디비전 및 팀의 목록으로 구성되고 팀 세부 정보 보기를 포함하는 스포츠 팀 계층 구조의 보기를 만듭니다. 목록에서 항목을 선택하면 이후 보기가 자동으로 업데이트됩니다.
팁 (조언)
마스터/세부 UWP 샘플도 참조하세요.
필수 조건
이 문서에서는 기본 WinUI 앱을 만드는 방법을 알고 있다고 가정합니다. 첫 번째 WinUI 앱을 만드는 방법에 대한 지침은 WinUI 앱 만들기를 참조하세요.
프로젝트 만들기
새 Blank App, Packaged(데스크톱의 WinUI 3) 프로젝트를 만듭니다. 이름을 'MasterDetailsBinding'으로 지정합니다.
데이터 모델 만들기
프로젝트에 새 클래스를 추가하고 이름을 ViewModel.cs로 지정한 후 다음 코드를 추가합니다. 이 클래스는 바인딩 소스 클래스입니다.
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
};
}
}
}
보기 만들기
그런 다음 마크업 페이지를 나타내는 클래스에서 바인딩 소스 클래스를 노출합니다.
LeagueList에 형식 의 속성을 추가합니다.
namespace MasterDetailsBinding
{
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ViewModel = new LeagueList();
}
public LeagueList ViewModel { get; set; }
}
}
마지막으로 MainWindow.xaml 파일의 내용을 다음 태그로 바꿉니다. 이 태그는 세 개의 CollectionViewSource 인스턴스를 선언하고 체인에 함께 바인딩합니다. 그러면 이후 컨트롤은 계층 구조의 수준에 따라 적절한 CollectionViewSource에 바인딩할 수 있습니다.
<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>
CollectionViewSource에 직접 바인딩하는 경우 컬렉션 자체에서 경로를 찾을 수 없는 바인딩의 현재 항목에 바인딩하려는 것을 의미합니다. 모호성이 있는 경우 추가할 수 있지만 바인딩의 경로로 속성을 지정할 CurrentItem 필요는 없습니다. 예를 들어 팀 보기를 나타내는 ContentControl 그러나 DataTemplate의 컨트롤은 Team이(가) 필요할 때 팀 목록에서 현재 선택된 팀을 자동으로 제공하기 때문에 CollectionViewSource 클래스의 속성에 바인딩됩니다.
참고 항목
Windows developer