User Control ๊ณผ Vimewodel

์•ˆ๋…•ํ•˜์„ธ์š”.
๊ณต๋ถ€ํ•˜๊ณ  ์žˆ๋Š” ํ•™์ƒ์ž…๋‹ˆ๋‹ค.

WPF๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ MVVM ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค๋Š”๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ๊นŒ์ง€ ์ œ๊ฐ€ ์ดํ•ดํ•œ View์™€ Viewmodel์€ ์ด๋ ‡์Šต๋‹ˆ๋‹ค.

View โ†’ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ผ ์š”์†Œ๋“ค์„ ๊ตฌ์„ฑํ•˜๋Š” ํŽ˜์ด์ง€
ViewModel โ†’ ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚ผ ์š”์†Œ๋“ค์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ํŽ˜์ด์ง€

์—ฌ๊ธฐ์„œ ํŽ˜์ด์ง€๋ผ ํ•จ์€ ๊ทธ๋ƒฅโ€ฆ ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ•ด์•ผ ํ• ์ง€ ๋ชฐ๋ผ์„œ ์–˜๊ธฐํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์œˆ๋„์šฐ ์ฐฝ์œผ๋กœ ๊ตฌ์„ฑ๋œ ๋ทฐ์™€ ๋ทฐ๋ชจ๋ธ์„ ์—ฐ๊ฒฐ์‹œํ‚ค๊ณ  ๋ฐ”์ธ๋”ฉ ํ•˜๋Š”๊ฒƒ์€ ์–ด๋А์ •๋„ ์ดํ•ด๊ฐ€ ๋˜์—ˆ๊ณ , UserControl์„ ์ฐพ๋‹ค๋ณด๋‹ˆ gpt๊ฐ€ usercontrol๋„ Viewmodel์„ ๊ฐ€์ง€๋Š”๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด ๋‹ค๋ผ๊ณ  ์ œ์‹œํ•˜์—ฌ ์ฐพ๋‹ค๋ณด๋‹ˆ UserControl์€ ๋ทฐ๋ชจ๋ธ์„ ๊ฐ€์ง€์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค. ๋ผ๋Š” ์˜๊ฒฌ์ด ์žˆ๋”๋ผ๊ตฌ์š”.

๊ฐํžˆ GPT์˜ ๋ง์„ ๊ฑฐ์Šค๋ฅด๋ ค๋Š”๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ๊ฒฐ๊ตญ userControl๋„ Control์ด๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„๊ฒƒ ๋ณด๋‹ˆ.. ์ผ๋ฐ˜์ ์ธ ๋ฒ„ํŠผ๋“ค๋„ ๋ทฐ๋ชจ๋ธ์ด ์—†์œผ๋‹ˆ๊นŒ Viewmodel์„ ํ†ตํ•œ ๋กœ์ง์ฒ˜๋ฆฌ๊ฐ€ ์–ด๋ถˆ์„ฑ์„ค์ด๋‹ค ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค๋”๋ผ๊ตฌ์š”.

์—ฌ๊ธฐ์„œ ์ œ๊ฐ€ ๊ถ๊ธˆํ•œ๊ฒƒ์€ ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ์–ด๋–ค ๋ฐฉ๋ฒ•์ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋” ๋งŽ์ด ์“ฐ์ด๋Š”์ง€,
๋ทฐ๋ชจ๋ธ์„ ํ†ตํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์–ด๋–ค์‹์œผ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

์šฐ์ธก ๋ฒ„ํŠผ๋“ค์„ ์ˆœ์ฐจ์ ์œผ๋กœ 1๋ฒˆ 2๋ฒˆ 3๋ฒˆ์ด๋ผ ํ•˜๊ณ  1๋ฒˆ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด 1๋ฒˆ usercontrol์„ ์ขŒ์ธกํƒญ์— ๋กœ๋“œํ•˜๊ณ  2๋ฒˆ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด 2๋ฒˆ usercontrol์„
์ขŒ์ธกํƒญ์— ๋กœ๋“œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด๋˜๋‚˜์š”??

๋„ˆ๋ฌด ๊ธฐ๋ณธ์ ์ธ ์งˆ๋ฌธ์ด๋ผ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค

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

MVVM ์€ WPF์™€ ํ•จ๊ป˜ ์†Œ๊ฐœ๋˜๊ธฐ๋Š” ํ–ˆ์ง€๋งŒ, WPF์— ํ•œ์ •๋œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.
์œˆํผ์—๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ•˜๋‹ค ๋ชปํ•ด ์ฝ˜์†”์•ฑ์—๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์งˆ๋ฌธ์˜ ๊ทธ๋ฆผ์œผ๋กœ ์„ค๋ช…์„ ๋“œ๋ฆฌ๋ฉด,

์ฒซ์งธ๋กœ ๊ทธ๋Ÿฌํ•œ ๋ชจ์–‘์œผ๋กœ ๋ณด์ด๋„๋ก ํ•˜๋Š” ๊ฒƒ์€ View์˜ ์—ญํ• ์ž…๋‹ˆ๋‹ค.
์šฐ์ธก์˜ ๋„ค๋ชจ๋‚œ ์ƒ์ž๊ฐ€ ๋ฒ„ํŠผ์ด๋ผ๋ฉด, ๋ฒ„ํŠผ ๋ชจ์–‘์œผ๋กœ ๋ณด์ด๊ฒŒ ํ•˜๋Š” ๊ฒƒ๋„, ๋ฒ„ํŠผ ์ฒ˜๋Ÿผ ํ–‰๋™ํ•˜๋Š” ๊ฒƒ - ํด๋ฆญํ•˜๋ฉด ๋ˆŒ๋ ค์ง€๋Š” ์•ก์…˜์„ ํ•˜๋Š” ๊ฒƒ๋„ ๋ทฐ์˜ ์—ญํ• ์ž…๋‹ˆ๋‹ค.

๋‘˜์งธ๋กœ, ๋ฒ„ํŠผ์ด ์šฐ์ธก์—์„œ ์ขŒ์ธก์œผ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ๋„ View ์˜ ์ผ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๊ทธ ๋„˜๊น€์˜ ์˜๋ฏธ๊ฐ€, ๋กœ์ง์  ์˜๋ฏธ - ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ถ”๊ฐ€๋‚˜ ์‚ญ์ œํ•  ํ•ญ๋ชฉ์„ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด, ๊ทธ ํ•ญ๋ชฉ์˜ ๊ด€๋ฆฌ๋Š” ViewModel ์˜ ์—…๋ฌด์ž…๋‹ˆ๋‹ค.

public class ViewModel
{
   // ๋กœ์ง์„ ์œ„ํ•œ ์ƒํƒœ
   public List<Item> Stored {get; set;} = [];
   public List<Item> Temp { get set; } = [];

   // ๋กœ์ง
   public void MoveToTemp(string itemName)
   {
      if (Stored.FirstOrDefault(x => x.Name == itemName) is Item item)
         Temp.Add(item);
   } 
}
// Psuedo View
<LeftSection> 
   <ItemsGrid/> // _viewModel.Temp ์— ๋ฐ”์ธ๋”ฉ
</LeftSectoin>
<RightSection>
   <ItemsStack/> // _viewModel.Stored ์— ๋ฐ”์ธ๋”ฉ
</RightSection>
// View Code-behind
private ViewModel _viewModel;

private void OnButtonOnItemStackClicked(object? s, EventArgs e)
{
   if (s is Button button) 
   {
      _viewModel.MoveToTemp(button.Text);
   }   
}

๋ณด์‹œ๋‹ค์‹œํ”ผ, ๋ทฐ๋Š” ๋ทฐ๋ชจ๋ธ์˜ ์ƒํƒœ๋ฅผ ํ™”๋ฉด์— ๋ฐ˜์˜ํ•˜๊ธฐ๋งŒ ํ•  ๋ฟ ์Šค์Šค๋กœ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ๋ทฐ๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ , ๋ทฐ๋ชจ๋ธ์— ์žˆ๋Š” ๋กœ์ง์„ (์ฝ”๋“œ ๋น„ํ•˜์ธ๋“œ์—์„œ) ํ˜ธ์ถœํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.

๋ทฐ์™€ ๋ทฐ๋ชจ๋ธ ์‚ฌ์ด์— ํ†ต์‹ ์€ ์ฝ”๋“œ ๋น„ํ•˜์ธ๋“œ(Command)์™€ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ(Query)์„ ํ†ตํ•ด ์ด๋ค„์ง์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ทฐ๋ชจ๋ธ์ด ์ด๋ ‡๊ฒŒ ์„ค๊ณ„๋˜์–ด ์žˆ๋‹ค๋ฉด, ์ด ๋ทฐ๋ชจ๋ธ์€ ์œˆํผ, ์ฝ˜์†” ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์–ด๋–ค UI ํ”„๋ ˆ์ž„์›Œํฌ์—๋„, ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์„ค๊ณ„ํ•˜๋ฉด ๋ทฐ์™€ ๋กœ์ง์ด ๋ถ„๋ฆฌ๋๋‹ค๊ณ  ๋ณด๋Š” ๊ฒƒ์ด๋ฉฐ, MVVM์ด ์ถ”๊ตฌํ•˜๋Š” ๋ฐ”์ž…๋‹ˆ๋‹ค.

MVVM์ด ์ž˜ ์ง€์ผœ์ง€๊ณ  ์žˆ๋Š” ์ง€, ๋ณด๋‹ค ์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด, ๋กœ์ง๊ณผ ๋ทฐ๊ฐ€ ์ ์ ˆํ•˜๊ฒŒ ๋ถ„๋ฆฌ๋˜์—ˆ๋Š” ์ง€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด ๋ทฐ๋Š” ์†์„ ์•ˆ๋Œ€๊ณ , ๋กœ์ง๋งŒ ๋ณ€ํ™”์‹œ์ผœ๋„ ์ „์ฒด ์†Œํ”„ํŠธ์›จ์–ด์— ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

public class ViewModel
{
   // ...

   // ๋กœ์ง ๊ตฌํ˜„์˜ ์ˆ˜์ •
   public void MoveToTemp(string itemName)
   {
      if (Stored.FirstOrDefault(x => x.Name == itemName) is Item item
         && Temp.FirstOrDefault(x => x.Name == itemName) is null)
         Temp.Add(item);
   } 
}

WPF๋Š” MVVM์„ ์ง€์›ํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ํŒจํ„ด์„ ๋”ฐ๋ฅด๋ฉด ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์œ ์ง€ ๋ณด์ˆ˜ํ•  ๋•Œ ํŽธ๋ฆฌํ•œ ๊ฒƒ์€ ๋งž์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜, ๋ฐ˜๋“œ์‹œ ์—„๋ฐ€ํ•˜๊ฒŒ ๋”ฐ๋ผ์•ผ ํ•˜๋Š” ๊ฒƒ์ด ์ง„๋ฆฌ์ผ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.
์™œ๋ƒํ•˜๋ฉด, ๋Œ€๋ถ€๋ถ„์˜ ๋””์ž์ธ ํŒจํ„ด์€ ๋ฏธ๋ž˜์˜ ์œ ์ง€๋ณด์ˆ˜๋ผ๋Š” ์ˆ˜์ต์„ ์œ„ํ•ด ์˜ค๋Š˜์˜ ์†๊ฐ€๋ฝ ํ’ˆ์„ ์—ด์‹ฌํžˆ ํŒ” ๊ฒƒ์„ ์š”๊ตฌ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ ๋งŒํผ ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ๊ฐ€ ๋งŽ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

์ง€๊ธˆ ๋‹น์žฅ, ์ž์›์ด ๋ถ€์กฑํ•˜๋‹ค๋ฉด ์ฝ”๋“œ ๋น„ํ•˜์ธ๋“œ์— ๋‹ค ๋•Œ๋ ค ๋„ฃ๋Š” ์„ ํƒ์„ ํ•˜๋”๋ผ๋„, ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๋™์ž‘์‹œํ‚ค๋Š” ๊ฒƒ์—๋Š” ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ํ•ด๋ณด์‹œ๋ฉด, ์–ด๋–ค ๊ฒŒ ๋ถ„๋ฆฌ๋˜์–ด์•ผ ํ•  ๋กœ์ง์ธ ์ง€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒŒ ํ›จ์”ฌ ๋” ์–ด๋ ต๋‹ค๊ณ  ๋А๋‚„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

์‚ฌ์šฉ์ž ์ •์˜(user defined control) ์ปจํŠธ๋กค๊ณผ UserControl์„ ๊ตฌ๋ถ„ํ•ด์„œ ์ƒ๊ฐํ•˜์…”์•ผํ•ฉ๋‹ˆ๋‹ค.

  1. ์ผ๋ฐ˜์ ์œผ๋กœ View๋Š” Window ๋˜๋Š” UserControl ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

  2. View๋Š” ๋‹ค์ˆ˜๊ฐœ์˜ ์ปจํŠธ๋กค์˜ ์กฐํ•ฉ์œผ๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ ์ปจํŠธ๋กค์€ WPF์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ์ปจํŠธ๋กค์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ UserControl ํด๋ž˜์Šค ๋˜๋Š” ์ƒ์œ„ ์ปจํŠธ๋กค ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์•„ user defined control์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰ UserControl์€ View๋ฅผ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž ์ •์˜ ์ปจํŠธ๋กค์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ๋ชจ๋‘ ์“ฐ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” UserControl์€ 1์˜ View๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ UserControl์ด ์•„๋‹Œ 2์˜ user defined control์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฌธ์˜ ์ฃผ์‹  ํŽ˜์ด์ง€ ๊ตฌ์„ฑ์€ ์•Œ๊ณ  ๊ณ„์‹  ๋ฐฉ๋ฒ•๋Œ€๋กœ UserControl์„ ์ƒ์† ๋ฐ›์•„ View์— ํ•ด๋‹นํ•˜๋Š” 1, 2์˜ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜์‹œ๊ณ  View Model์„ ์ฐธ์กฐํ•˜์—ฌ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

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

๋‘๋ถ„ ๋‹ค ๋‹ต๋ณ€ ์ฑ„ํƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜์—ฌ ๊ทธ๋ƒฅโ€ฆ ๋‘๊ฒ ์Šต๋‹ˆ๋‹คโ€ฆ!
๋‘๋ถ„ ๋‹ค ์ง„์‹ฌ์œผ๋กœ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค

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

์ œ๊ฐ€ ์ดํ•ดํ•œ ๋ฐ”๊ฐ€ ๋งž๋Š”์ง€ ํ™•์ธ ์ฐจ ๋Œ“๊ธ€ ๋‚จ๊ฒจ๋ด…๋‹ˆ๋‹คโ€ฆ

View โ†’ Window/UserControl ๋กœ ๊ตฌํ˜„ํ•จ.
์ด Window์™€ UserControl์€ ๋‹ค์ˆ˜์˜ ์ปจํŠธ๋กค๋กœ ์กฐํ•ฉ๋จ.
์ด ๋•Œ ๋‹ค์ˆ˜์˜ ์ปจํŠธ๋กค์€ WPF์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ Cotrol๊ณผ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” userDefined Control์„ ์˜๋ฏธํ•จ.

User Defined Control ์€ WPF์—์„œ ์ œ๊ณตํ•˜๋Š” Control๊ณผ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ViewModel์„ ๊ฐ€์งˆ ํ•„์š” ์—†์Œ.
User Control์€ ์ผ๋ฐ˜์ ์ธ View์— ํ•ด๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— ViewModel์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋จ.

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

๋„ต. ์ดํ•ดํ•˜์‹  ๋‚ด์šฉ์ด ๋งž์Šต๋‹ˆ๋‹ค:blush:

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