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

[๊ฒฐ๊ณผ]

์ข‹์•„์š” 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 ์ž˜ ์„ค๋ช…ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.!