WPF ContentTemplate에서 Binding 문제

안녕하세요. :smile:

WPF DataTemplate 영역은 적용이 되는데 Binding이 되질 않습니다.
어떤 문제가 있을까요?

간단하게 되는 것으로 알고 있었는데…
ContentTemplate 안에서 Binding을 인식하지 못하네요.

아래 소스는 간소화 시킨 부분입니다.

<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border Padding="10" Background="#eeeeee">
                    <StackPanel>
                        <TextBlock Text="Original"/>
                        <TextBlock Text="{Binding}"/>
                        <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
                                          DataContext="{Binding}"/>
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Border Padding="10" Background="#aaaaaa" Margin="10">
                    <StackPanel>
                        <TextBlock Text="Custom"/>
                        <TextBlock Text="{Binding}"/>
                    </StackPanel>
                </Border>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

image

혹시 제가 빼먹거나 잘못 한 부분이 있을까요?

읽어주셔서 감사합니다. :smile:

1개의 좋아요

올려주신 xaml코드상으로는 문제는 없어 보입니다.

바인딩 경로가 잘못 되어 내부적으로 오류가 나서 표시가 안되고 있는 것일 수 있습니다.

실제 사용되는 Button의 Content영역과 해당 바인딩 대상의 ViewModel부분도 같이 봐야 문제점을 파악할 수 있을 것 같습니다.

VS에서 [출력]창에 바인딩 관련 오류가 찍혀 있지 않는지 다시한번 확인해 보세요!

  • 참고 : ContentPresenter에서 바인딩 영역이 다른 ViewModel이 아니라면 DataContext는 생략하셔도 됩니다.
2개의 좋아요

@aroooong 제가 설명이 부족했네요. 죄송합니다. :joy:

말씀해주신 것 처럼 제가 생각하기에도 문제가 없어 보였지만…
ContentTemplate까지 DataContext가 도달하지 않고 있습니다.

GitHub에 테스트한 샘플 소스코드도 올려두겠습니다!

그리고 제가 오픈소스로 만들고 있는 프로젝트(DevFlow)도 똑같은 증상입니다.

신경써주셔서 감사합니다! :smile:


MainWindow.xaml

<Window x:Class="WpfApp6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp6"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
		<Button/>
	</Grid>
</Window>

App.xaml

<Style TargetType="Button">
	<Setter Property="Template">
		<Setter.Value>
			<ControlTemplate TargetType="Button">
				<Border Padding="10" Background="#eeeeee">
					<StackPanel>
						<TextBlock Text="Original"/>
						<TextBlock Text="{Binding}"/>
						<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
											DataContext="{Binding}"/>
					</StackPanel>
				</Border>
			</ControlTemplate>
		</Setter.Value>
	</Setter>
	<Setter Property="ContentTemplate">
		<Setter.Value>
			<DataTemplate>
				<Border Padding="10" Background="#aaaaaa" Margin="10">
					<StackPanel>
						<TextBlock Text="Custom"/>
						<TextBlock Text="{Binding}"/>
					</StackPanel>
				</Border>
			</DataTemplate>
		</Setter.Value>
	</Setter>
</Style>
</Application.Resources>

MainViewModel.cs

public class MainViewModel
{
}

음., 제가 문제를 정확히 파악 하지 못한걸까요…?

올려주신 MainViewModel에는 비어 있고

실제 사용되는 Button에도 Content속성이 비어 있는 상태에서

ContentTemplate영역에
TextBlock Text=“{Binding}” <-는 값이 당연히 비어 있는게 정상 아닌가요??

다음과 같이 바꿔보면 정상 바인딩 됩니다.

[MainViewModel.cs]
image

[MainWindow.xaml]
image

[결과]
image

2개의 좋아요

혹여나… 참고로
ControlTemplate 영역의 Binding은
자기 자신의 DataContext의 객체가 내부적으로 ToString되서 풀 네임스페이스 경로가 찍힌 것이고

ContentTemplate영역의 Binding은
버튼의 Content영역에 지정된 값을 바라보기에… 해당 Content는 지정되지 않아 아무 표시가 되지 않는 것 입니다.

1개의 좋아요

@aroooong 정확한 답변 감사드립니다. :smile:

설명주신대로 ContentPresenter는 기본적으로 Content가 연결되어 있는데
당연히 나오지 않는 것을 제가 엉뚱하게 시도해보고 있었네요. :joy:

ContentPresenter에 있는 DataTemplate은 DataContext와 무관하다는 것도 알게 되었습니다.

말씀해주신 부분 이해하고 이렇게 처리했습니다.

<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                               Content="{Binding}"/>

그리고 ContentSource를 활용하는 방법도 알게 되었습니다.
(기본 값이 Content인 것 같습니다.)

<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                  ContentSource="DataContext"/>

@aroooong 잘 설명해주셔서 감사합니다.!