포스트

WPF DataTemplateSelector 완전 정복 - 조건에 따라 다른 UI 그리기

WPF DataTemplateSelector 완전 정복 - 조건에 따라 다른 UI 그리기

WPF에서는 DataTemplate 을 사용하여 View 와 ViewModel을 깔끔하게 분리할 수 있습니다. 그런데 하나의 리스트에 다양한 형태의 데이터가 들어오는 경우, 어떤 템플릿을 써야할까요?
바로 그때 사용하는 게 DataTemplateSelector입니다.

목표

  • 하나의 ListBox에 여러 타입의 아이템 표시
  • 혹은 속성 값에 따라 다른 템플릿 적용

예제 구조

1
2
3
4
5
6
7
8
9
10
11
abstract class Notification { }

class TextNotification : Notification
{
    public string Message { get; set; }
}

class ImageNotification : Notification
{
    public string ImagePath { get; set; }
}

1. DataTemplateSelector 클래스 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.Windows;
using System.Windows.Controls;

public class NotificationTemplateSelector : DataTemplateSelector
{
    public DataTemplate? TextTemplate { get; set; }
    public DataTemplate? ImageTemplate { get; set; }

    public override DataTemplate? SelectTemplate(object item, DependencyObject container)
    {
        return item switch
        {
            TextNotification => TextTemplate,
            ImageNotification => ImageTemplate,
            _ => base.SelectTemplate(item, container)
        };
    }
}

타입 기반으로 템플릿을 선택합니다.

2. XAML 리소스 정의

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Window.Resources>
    <!-- 각각의 템플릿 정의 -->
    <DataTemplate x:Key="TextTemplate" DataType="{x:Type local:TextNotification}">
        <TextBlock Text="{Binding Message}" Foreground="DarkBlue"/>
    </DataTemplate>

    <DataTemplate x:Key="ImageTemplate" DataType="{x:Type local:ImageNotification}">
        <StackPanel Orientation="Horizontal">
            <Image Source="{Binding ImagePath}" Width="32" Height="32"/>
            <TextBlock Text="이미지 알림!" Margin="5,0,0,0"/>
        </StackPanel>
    </DataTemplate>

    <!-- 템플릿 선택기 선언 -->
    <local:NotificationTemplateSelector x:Key="NotificationSelector"
                                        TextTemplate="{StaticResource TextTemplate}"
                                        ImageTemplate="{StaticResource ImageTemplate}"/>
</Window.Resources>

3. ListBox에 적용

1
2
<ListBox ItemsSource="{Binding Notifications}"
         ItemTemplateSelector="{StaticResource NotificationSelector}"/>

4. ViewModel 샘플

1
2
3
4
5
6
7
8
9
public class MainViewModel
{
    public ObservableCollection<Notification> Notifications { get; } = new()
    {
        new TextNotification { Message = "새 메일이 도착했습니다." },
        new ImageNotification { ImagePath = "/Assets/info.png" },
        new TextNotification { Message = "업데이트가 완료되었습니다." }
    };
}

결과

  • TextNotification 인 경우에는 파란색 텍스트로 메시지 출력
  • ImageNotification 인 경우에는 아이콘 + 안내 문구 표시

고급 사용 팁

  • DataTemplateSelector 는 타입뿐 아니라 속성 값으로도 구분 가능 예: item is Notification n && n.Priority == High
  • ContentControl, ItemsControl, TreeView, ListView 어디서든 사용 가능
  • MVVM 환경에서 ViewModel을 조건 분리하지 않고 View에서 깔끔하게 처리 가능

마무리

DataTemplateSelector 는 WPF 에서 동적인 UI 구성이 필요할 때 매우 강력한 도구입니다.
뷰모델을 수정하지 않고도 다양한 시각적 표현을 유연하게 분기할 수 있습니다.

이런 경우에 특히 유용:

  • 채팅 앱에서 메시지 유형이 다를 때
  • 파일 탐색기에서 파일, 폴더, 템플릿을 다르게 보여줄 때
  • 알람 리스트에 텍스트/이미지/링크 등 다양한 형식을 보여줄 때
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.