WPF 여러 개의 DataTemplate을 지정하는 방법은?

안녕하세요 :smile:

WPF에서 DataTemplate을 여러 개 지정할 수 있는 방법이 있을까요?

예를들어 ListBoxItem의 DataTemplate 지정 코드입니다.

<Setter Property="ContentTemplate" Value="{StaticResource Electric}"/>

이렇게 하나를 지정할 수 있지만, 데이터테이블이 여러 개 일 때에도 x:Key를 통해 정확히 지정하고 싶은데요.

DataTemplate Key를 지정하지 않는다면 데이터 타입에 따라 알아서 적용되겠지만, x:Key는 명확하게 주고 싶습니다.

그리고 제가 예전에 했던 방법으로는 Trigger를 이용해 DataContext Type에 따라 ContentPresenter Template을 바꿔주는 방식이었는데, 제 기억에는 Trigger 시점에서 DataTemplate이 변경되기 떄문에 Runtime에서 UI에 어떠한 영향을 줄 수도 있기 때문에 문제가 있었던 것 같습니다.


아래는 참고용 샘플 소스코드입니다.

<DataTemplate x:Key="Electric" DataType="{x:Type model:Electric}">
    <TextBlock Text="{Binding Battery}"/>
</DataTemplate>
<DataTemplate x:Key="Gasoline" DataType="{x:Type model:Gasoline}">
    <TextBlock Text="{Binding Litter}"/>
</DataTemplate>
        
<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="ContentTemplate" Value="{StaticResource Electric}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <Border Background="#FFFFFF">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <CheckBox Grid.Column="0"/>
                        <ContentPresenter Grid.Column="1"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

샘플은 프로젝트로 간단하게 만들어서 첨부하도록 하겠습니다!

샘플 프로젝트 GitHub

읽어주셔서 감사합니다.

좋아요 1

우선 ControlTemplate.Resource 안에 넣어 x:Key 없이 사용했습니다. :smile:

<ControlTemplate.Resource>
    <DataTemplate DataType="{x:Type model:Electric}">
        <TextBlock Text="{Binding Battery}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type model:Gasoline}">
        <TextBlock Text="{Binding Litter}"/>
    </DataTemplate>
</ControlTemplate.Resource>

안쓴지 오래되어 기억이 가물가물하지만, ContentTemplateSelector를 써서 했었던 기억인데요, Selector를 쓰면 되지 않을까요?

ContentControl.ContentTemplateSelector 속성 (System.Windows.Controls) | Microsoft Docs

좋아요 2

@dimohy 감사합니다. :smile:

제가 정확히 원하던 답입니다!

public class CarTemplateSelector : DataTemplateSelector
{
    public DataTemplate ElectricTemplate { get; set; }
    public DataTemplate GasolineTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, 
        DependencyObject container)
    {
        if (item is Electric)
        {
            return ElectricTemplate;
        }
        else if (item is Gasoline)
        {
            return GasolineTemplate;
        }
        return base.SelectTemplate(item, container);
    }
}

DataTemplate을 좀 더 밀도있게 사용할 수 있을 것 같습니다.

<DataTemplate x:Key="DATA_ELECTRIC" DataType="{x:Type model:Electric}">
    <TextBlock Text="{Binding BatteryCharge}"/>
</DataTemplate>
<DataTemplate x:Key="DATA_GASOLINE" DataType="{x:Type model:Gasoline}">
    <TextBlock Text="{Binding Displacement}"/>
</DataTemplate>

<selector:CarTemplateSelector x:Key="CarTemplateSelector"
                              ElectricTemplate="{StaticResource DATA_ELECTRIC}"
                              GasolineTemplate="{StaticResource DATA_GASOLINE}"/>

...
<Setter Property="ContentTemplateSelector" 
        Value="{StaticResource CarTemplateSelector}"/>

감사합니다!

(샘플에도 적용했습니다.)

좋아요 2