Template vs UserControl

WPF ๋ˆ์ด ์งง์•„์„œ ์ด๋Ÿฐ ๊ณ ๋ฏผ์„ ์‹œ์ž‘ํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

WPF๋Š” View๋ฅผ ๊ตฌ์„ฑํ•จ์— ์žˆ์–ด UserControl์ด UserControl์„ ์ž์‹์œผ๋กœ ๋‘๊ณ , ๋˜ ๊ทธ UserControl์ด UserControl์„ ์ž์‹์œผ๋กœ ๋‘๋ฉด์„œ UserControl์—๋„ Layer๋ฅผ ๋‚˜๋ˆ  view๋ฅผ ์ตœ๋Œ€ํ•œ ์žฌ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋„๋ก ๋ชจ๋“ˆํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ํ”„๋ฆฌ์ฆ˜์ด ๊ทธ๋Ÿฐ ๊ฒƒ์ด์ฃ . (์•ˆ์จ๋ดค์ง€๋งŒ)

์ด ๋•Œ UserControl์„ ๋งŒ๋“ค ๋•Œ๋Š” ์›ฌ๋งŒํ•˜๋ฉด ๋ถ€๋ชจ-์ž์‹ ๊ฐ„ Binding ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ ์ž์‹ ์ž…์žฅ์ด ๋˜๋Š” UserControl์—์„œ DependencyProperty๋ฅผ ๋งŒ๋“ค์–ด์„œ(์ œ๊ณตํ•ด์„œ) ๋ถ€๋ชจ์ปจํŠธ๋กค์—์„œ ๋ถ€๋ชจ์ปจํŠธ๋กค์˜ ViewModel์ด ๋ฐ”์ธ๋”ฉ ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์ œ๊ฐ€ ์ƒ๊ฐํ–ˆ์„ ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ์š”.
์ง€๊ธˆ๋ถ€ํ„ฐ UserControl์„ uc๋ผ๊ณ  ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


A uc, B uc, C uc๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

  • A๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์œผ๋กœ ์“ฐ์ผ ์žฌ์‚ฌ์šฉ๋ฅ ์ด ๋†’๊ณ  ๊ฐ€์žฅ ๊ธฐ๋ณธ๋‹จ์œ„์˜ uc์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ A๋Š” ๊ธฐ๋ณธ WPF ์ปจํŠธ๋กค๋กœ๋งŒ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. DP๋ฅผ 2๊ฐœ ์ •์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹จ์ˆœํ•˜๊ฒŒ view์˜ ์—ญํ• ๋งŒ ํ•˜๊ณ  ์žˆ์–ด, ViewModel(์ดํ•˜ vm)์ด ๋”ฑํžˆ ํ•„์š”์—†๊ธฐ ๋•Œ๋ฌธ์— DataContext = this; ๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • B๋Š” A๋ฅผ ์ž์‹์ปจํŠธ๋กค์œผ๋กœ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. B๋„ DP๊ฐ€ ํ•„์š”ํ•˜์—ฌ 2๊ฐœ ์ •์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์—ญ์‹œ A์ฒ˜๋Ÿผ view์˜ ์—ญํ• ๋งŒ ํ•˜๊ณ  ์žˆ์–ด์„œ DataContext = this; ๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • C๋Š” B๋ฅผ ์ž์‹์ปจํŠธ๋กค์œผ๋กœ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. C์—๋Š” vm์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด C-vm์˜ ๋ฐ์ดํ„ฐ๋ฅผ B์— Binding ํ•˜๋ ค๋Š”๋ฐ B์˜ A uc์— ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. A๋Š” B๋กœ ๊ฐ์‹ธ์ ธ ์žˆ์œผ๋‹ˆ C๋Š” B ๋ฐ–์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๋ฐฉ๋ฒ•์€ B์— A์™€ ๋˜‘๊ฐ™์€ DP๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๊ณ  B์—์„œ ๋งŒ๋“  DP๋กœ C์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ์™€ A์˜ ์ปจํŠธ๋กค์„ ์„œ๋กœ ๋ฐ”์ธ๋”ฉ์œผ๋กœ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ๊ฒƒ์ธ๋ฐ์š”.

๊ทธ๋Ÿผ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ตฌ์กฐ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
A์ปจํŠธ๋กค
A์ปจํŠธ๋กค

B์ปจํŠธ๋กค
B์ปจํŠธ๋กค

C์ปจํŠธ๋กค
C์ปจํŠธ๋กค

ํ˜„์žฌ B์— A์˜ DP๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์€ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

์ด๊ฑธ ๊ทธ๋Ÿผ ๊ทธ๋ƒฅ ๋งŒ๋“ค์–ด์„œ C โ†’ B โ†’ A ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์ „๋‹ฌ๋˜๋„๋ก ํ•˜๋ ค๋‹ค๊ฐ€, ๋งŒ์•ฝ์— ์ง€๊ธˆ ์ด๊ฑฐ์•ผ ๊ณ ์ž‘ 2์ธต๊ตฌ์กฐ์ง€๋งŒ, ๋‚˜์ค‘์— 5์ธต, 10์ธต ๊ตฌ์กฐ์˜ uc๊ฐ€ ๋‚˜์˜จ๋‹ค๋ฉด ์ตœ์ข… uc๊นŒ์ง€ ๊ฐ€๋ฉด์„œ ์•ฝ๊ฐ„ ๊ณ„์ฐจ์ˆ˜์—ด ์˜ ๊ฐœ๋…๊ณผ ์œ ์‚ฌํ•œ๋งŒํผ dp๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์ปจํŠธ๋กค๊ณผ ์ปจํŠธ๋กค ์‚ฌ์ด์˜ dp๋ฅผ ์–ผ๋งˆ๋‚˜ ์ƒ์„ฑํ•ด์ฃผ๋А๋ƒ์— ๋”ฐ๋ผ ๊ทธ ๋‹ค์Œ ์ปจํŠธ๋กค์˜ dp๊ฐ€ ๋Š˜์–ด๋‚จ.)

๊ทธ๋Ÿผ ์ด ์˜ˆ์ œ์—์„œ๋Š” B๋Š” A์˜ DP 2๊ฐœ๋ฅผ ๋˜‘๊ฐ™์ด ๋งŒ๋“ค์–ด์„œ ์ „๋‹ฌ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค Command 2๊ฐœ๋ฉด๋˜๋Š”๋ฐ A ๋•Œ๋ฌธ์— DP๊ฐ€ ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์ด์ฃ .


์‚ฌ์‹ค Template์„ ์ด์šฉํ•˜๋ฉด Control์„ ๊ฒน๊ฒน์ด๋กœ ์Œ“์€ ๊ตฌ์กฐ๊ฐ€ ์•„๋‹ˆ๊ณ  1์ฐจ์›์ ์ธ ๊ตฌ์กฐ๋‹ค๋ณด๋‹ˆ Binding์ด ์‰ฝ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ๋ชจ๋“  view์˜ ๋ชจ๋“ˆํ™”๋ฅผ template์œผ๋กœ ํ•ด์•ผํ•˜๋Š”์ง€โ€ฆ๋งŒ์•ฝ template์œผ๋กœ ํ•œ๋‹ค๋ฉด dp๋Š” ์–ด๋–ค ์‹์œผ๋กœ ์šฐํšŒ์‹œํ‚ฌ์ง€ ๊ฐ์ด ์ž˜ ์•ˆ์˜ต๋‹ˆ๋‹ค.

์ œ๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ๋ฐฉ๋ฒ• ์™ธ์— ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ์š”?

2๊ฐœ์˜ ์ข‹์•„์š”

๋„์›€์„ ๋“œ๋ฆฌ๊ณ  ์‹ถ์€๋ฐ ์ •๋ฆฌ๋ฅผ ๋จผ์ € ํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์•„์„œ์š”.

  • B๊ฐ€ A๋ฅผ ํ’ˆ๊ณ  ์žˆ๋‹ค.
  • C๊ฐ€ B๋ฅผ ํ’ˆ๊ณ  ์žˆ๋‹ค.
  • C๋Š” ViewModel์ด ์žˆ๋‹ค.
  • C์—์„œ B๊ฐ€ ํ’ˆ๊ณ  ์žˆ๋Š” A์— ๋ฐ”์ธ๋”ฉ ํ•ด์•ผ ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ๋งž๋Š”๊ฑธ๊นŒ์š”?

3๊ฐœ์˜ ์ข‹์•„์š”

์ •ํ™•ํ•˜์‹ญ๋‹ˆ๋‹ค. A๋Š” ์‚ฌ์‹ค Textbox๋ฅผ ํ’ˆ๊ณ ์žˆ๋Š” uc์ผ ๋ฟ์ด๊ณ  C์—์„œ A์˜ Textbox์— ๋ฐ”์ธ๋”ฉํ•ด์•ผํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2๊ฐœ์˜ ์ข‹์•„์š”

์ƒ˜ํ”Œ๋กœ ์ž‘์„ฑํ•œ๊ฑฐ๋ผ ์–‘ํ•ด ๋ฐ”๋ž„๊ฒŒ์š”.
ํ˜น์‹œ ์ด๋Ÿฐ ํ˜•ํƒœ๋ฅผ ๋ง์”€ํ•˜์‹œ๋Š” ๊ฒƒ์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋„ค์š”.

C ๋Š” MainWindow, MainViewModel๋กœ ์ •์˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
MainViewModel์€ B ์†์„ฑ์œผ๋กœ BViewModel์„ ํ’ˆ์Šต๋‹ˆ๋‹ค.
BViewModel์€ A ์†์„ฑ์œผ๋กœ AViewModel์„ ํ’ˆ์Šต๋‹ˆ๋‹ค.
AViewModel์—๋Š” ๋ฐ”์ธ๋”ฉ ๋Œ€์ƒ์ธ Text ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ViewModels

public class MainViewModel : ObservableObject
{
    private BViewModel _b;
    public BViewModel B
    {
        get => _b;
        set => SetProperty(ref _b, value);
    }
}

public class BViewModel : ObservableObject
{
    private AViewModel _a;
    public AViewModel A
    {
        get => _a;
        set => SetProperty(ref _a, value);
    }
}

public class AViewModel : ObservableObject
{
    private string _text;
    public string Text
    {
        get => _text;
        set => SetProperty(ref _text, value);
    }
}

AView

<UserControl x:Class="WpfDemo.AView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfDemo"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBlock Text="{Binding Text}" />
    </Grid>
</UserControl>

BView

<UserControl x:Class="WpfDemo.BView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfDemo"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <StackPanel>
        <local:AView DataContext="{Binding A}"></local:AView>
    </StackPanel>
</UserControl>

MainWindow
ContentControl ๋Œ€์‹  BView๋ฅผ ์ง์ ‘ ์„ ์–ธํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค๋งŒ, ContentControl์„ ์„ ์–ธํ•˜๊ณ  Resource์— ViewModel๊ณผ View๋ฅผ ๋งคํ•‘ํ•˜์‹œ๋ฉด ๋ฐ”์ธ๋”ฉ๋œ ViewModel ํƒ€์ž…์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ View๋ฅผ ๋‹ฌ๋ฆฌ ์„ค์ •ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<Window x:Class="WpfDemo.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:WpfDemo"
        xmlns:viewModels="clr-namespace:WpfDemo.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ContentControl Content="{Binding B}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type viewModels:BViewModel}">
                    <local:BView DataContext="{Binding}" />
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>
    </Grid>
</Window>

View์™€ ViewModel ์—ฐ๊ฒฐ

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var viewModel = new MainViewModel
        {
            B = new BViewModel
            {
                A = new AViewModel
                {
                    Text = "Hello world"
                }
            }
        };

        DataContext = viewModel;
    }

image

MVVM ํ”„๋ ˆ์ž„์›Œํฌ๋กœ Microsoft.Toolkit.Mvvm์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค~
image

4๊ฐœ์˜ ์ข‹์•„์š”

ํ•˜ํ•˜โ€ฆ์ •๋ง View์˜ ๊ธฐ๋Šฅ๋งŒํ•˜๊ณ  ์ƒ์œ„ ์ปจํŠธ๋กค๋กœ ๋ฐ”์ธ๋”ฉ ์ฑ„๋„๋งŒ ์—ด์–ด์ค€์ฑ„๋กœ ๋””ํ…Œ์ผํ•œ ๊ธฐ๋Šฅ์€ ๊ฐ€์žฅ ์ตœ์ƒ์œ„ ๋‹จ์—์„œ ๋ฐ”์ธ๋”ฉ ์ฒ˜๋ฆฌํ•  ๊บผ๋ผ์„œโ€ฆ ์ตœ์ƒ์œ„ ๋‹จ์—๋งŒ ViewModel์ด ์žˆ์œผ๋ฉด ๋  ๊ฑฐ๋ผ๋Š” ์ƒ๊ฐ์ด ๋…์ด ๋œ ๊ฑฐ ๊ฐ™๋„ค์š”. (B, A ์— DataContext = this;)

DP๋ฅผ ๋งŒ๋“ค ํ•„์š” ์—†์ด ํ•˜์œ„ view๋‹จ์—์„œ ๋ฐ”์ธ๋”ฉ์ด ๋ชจ๋‘ ๋˜์–ด ์žˆ์œผ๋‹ˆ๊นŒ ๊ฐ ViewModel ๋ผ๋ฆฌ ์˜์กดํ•ด์„œ ๋ฐ์ดํ„ฐ๋งŒ ๋„˜๊ธฐ๋ฉด ์•Œ์•„์„œ ํ‘œํ˜„์ด ๋˜๊ฒ ๊ตฐ์š”โ€ฆ

์˜ˆ์ œ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์ œ๊ฐ€ ๋ง์”€๋“œ๋ฆฐ ๊ฑด ViewModel์˜ ObservableProperty๊ฐ€ ์•„๋‹ˆ๋ผ uc์—์„œ ์‚ฌ์šฉ๋˜๋Š” DependencyProperty ์˜€์—ˆ๋Š”๋ฐ DP ๊ฑท์–ด๋‚ด๋„ ๋  ๊ฒƒ ๊ฐ™๋„ค์š”.

DP๋กœ ํ•ด์„œ View๋ผ๋ฆฌ ์„œ๋กœ ์˜์กดํ•˜๋„๋ก ํ•ด์„œ ๋งŒ๋“ค์–ด๋„ ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ์š”.

๋ง์”€ํ•˜์‹  ๋ฐฉ์‹์ด ํ›จ์”ฌ ํšจ์œจ ์ ์ผ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์‰ฝ๊ฒŒ ์‰ฝ๊ฒŒ ๊ฐ”์œผ๋ฉด ๋˜์—ˆ์„ ํ…๋ฐ ๊ดœํžˆ ์–ด๋ ต๊ฒŒ ํ•˜๋ ค ํ–ˆ๋˜๊ฑฐ๋„ค์š”.

๊นจ๋‹ฌ์Œ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

2๊ฐœ์˜ ์ข‹์•„์š”

์ข‹์€ ์ฃผ๋ง ๋˜์„ธ์š”~

2๊ฐœ์˜ ์ข‹์•„์š”

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ์ข‹์€ ์ฃผ๋ง๋˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค^^!

2๊ฐœ์˜ ์ข‹์•„์š”