MVP Sample for Winform

MVP Sample for Winform

์ด์ฒ ์šฐ

MVC ์—์„œ ๊ฐœ์„ ํ•œ ๊ฒƒ.

  • C# Winform์˜ DataBinding ๊ณผ INotifyPropertyChanged ๋ฅผ ์ด์šฉํ•˜์—ฌ
  • Model ๊ณผ View ์—์„œ
  • DataChangedEvent ๋ฅผ ๋บ๋‹ค.
  1. ๋จผ์ € Winform ํ”„๋กœ์ ํŠธ(.Net 7)๋ฅผ ๋งŒ๋“ ๋‹ค.
    0-1. ํ”„๋กœ์ ํŠธ ์†์„ฑ์—์„œ 'Console Applicationโ€™์„ ์„ ํƒํ•œ๋‹ค.
    0-2. Form1 ๋””์ž์ธ์—์„œ TextBoxData, ButtonReset, ButtonIncrease ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

  2. IView.cs

    public interface IView
    {
        TextBox TextBoxData { get; }

        event EventHandler<EventArgs>? ResetPressed;
        event EventHandler<EventArgs>? IncreasePressed;
    }
  1. Model.cs
    public class Model : INotifyPropertyChanged
    {
        public Model() { }
        public int Data
        {
            get => _data;
            set
            {
                if (_data != value)
                {
                    _data = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Data)));
                    Console.WriteLine(ToString());
                }
            }
        }
        private int _data = 0;

        public void Reset() => Data = 0;
        public void Increase() => Data++;
        public void Set(int data) => Data = data;

        public override string ToString() => $"Data:{Data}";

        public event PropertyChangedEventHandler? PropertyChanged;
    }

  1. Presenter.cs
    public class Presenter
    {
        public Model Model { get; private set; }
        public IView View { get; private set; }

        public Presenter(Model model, IView view)
        {
            Model = model;
            View = view;

            View.ResetPressed += View_ResetPressed;
            View.IncreasePressed += View_IncreasePressed;

            var binding = new BindingSource
            {
                DataSource = Model
            };
            View.TextBoxData.DataBindings.Add(new Binding("Text", binding, "Data", true, DataSourceUpdateMode.OnPropertyChanged));
        }

        private void View_ResetPressed(object? sender, EventArgs e)
        {
            Model.Reset();
        }
        private void View_IncreasePressed(object? sender, EventArgs e)
        {
            Model.Increase();
        }
    }
  1. IView ์ƒ์†๋ฐ›์€ Form1.cs
    public partial class Form1 : Form, IView
    {
        public Form1()
        {
            InitializeComponent();
        }

        TextBox IView.TextBoxData => TextBoxData;

        public event EventHandler<EventArgs>? ResetPressed;
        public event EventHandler<EventArgs>? IncreasePressed;

        private void ButtonReset_Click(object sender, EventArgs e)
        {
            ResetPressed?.Invoke(this, new EventArgs());
        }

        private void ButtonIncrease_Click(object sender, EventArgs e)
        {
            IncreasePressed?.Invoke(this, new EventArgs());
        }
    }

  1. Program.cs
    internal static class Program
    {
        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // To customize application configuration such as set high DPI settings or default font,
            // see https://aka.ms/applicationconfiguration.
            ApplicationConfiguration.Initialize();

            #region MVP Sample for Winform.
            var view = new Form1();
            var model = new Model();
            _ = new Presenter(model, view);
            #endregion

            Application.Run(view);
        }
    }
3๊ฐœ์˜ ์ข‹์•„์š”

๊ธ€ ์ž˜ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜น์‹œ, IView Interface๋กœ ๊ตฌํ˜„ํ•œ UserControl๋ผ๋ฆฌ, ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๊ฑฐ๋‚˜ ์ด๋ฒคํŠธ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ๋ง์”€ ๋ถ€ํƒ๋“œ๋ ค๋„ ๋ ๊นŒ์š”? ์˜ˆ๋ฅผ ๋“ค์–ด, ํ˜น์‹œ HTS๋ฅผ ์‚ฌ์šฉํ•˜์…จ๋‹ค๋ฉด, ์‹ค์‹œ๊ฐ„ ์ž”๊ณ ์— ์žˆ๋Š” ํ•œ ์ข…๋ชฉ์„ ํด๋ฆญํ•˜๋ฉด ๊ทธ ์ข…๋ชฉ์— ๋Œ€ํ•œ ์ฐจํŠธ ํŽ˜์ด์ง€์—์„œ๋„ ์ž๋™์œผ๋กœ ๊ทธ ์ข…๋ชฉ์˜ ์ฐจํŠธ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

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

[1] ํด๋ž˜์Šค [์‹ค์‹œ๊ฐ„ ์ž”๊ณ ]์—์„œ ์ด๋ฒคํŠธ [ํ•œ ์ข…๋ชฉ์„ ํด๋ฆญ]๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ์ธ์ˆ˜๋กœ [๊ทธ ์ข…๋ชฉ]์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

[2] ํด๋ž˜์Šค [์ฐจํŠธ ํŽ˜์ด์ง€]์—์„œ [1]์—์„œ ๋งŒ๋“  [ํ•œ ์ข…๋ชฉ์„ ํด๋ฆญ] ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ˆ˜๋กœ ๋ฐ›์€ [๊ทธ ์ข…๋ชฉ]์˜ ์ฐจํŠธ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

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

๋Œ€๊ฐœ์˜ ์ฆ๊ถŒ์‚ฌ HTS๋Š” ์˜ˆ์ „ ๊ธฐ์ˆ ์ด๋ผ .Net์œผ๋กœ ๋„˜์–ด๊ฐ€์ง€ ๋ชปํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
RESTful API๋กœ ๋„˜์–ด๊ฐ„ ๊ณณ์€ ํ•œํˆฌ, ๋””๋น„ ์ •๋„์ธ ๊ฒƒ์œผ๋กœ ์•Œ๊ณ ์žˆ์Šต๋‹ˆ๋‹ค.

.Net์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด, Winform MVVM ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

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

์ฐจํŠธ ํŽ˜์ด์ง€๊ฐ€ ์—ด๋ ค์žˆ๋‹ค๋ฉด, ์ด๋ฏธ ๊ทธ ์ข…๋ชฉ์˜ ์ฐจํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ๋Š” ์ƒํƒœ์ธ๋ฐ, ์ฐจํŠธ๋ฅผ ๋ฐ”๊ฟ€ ํ•„์š”๊ฐ€ ์žˆ์„๊นŒ์š”?

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

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค ์ œ๊ฐ€ ์„ค๋ช…์ด ๋ถ€์กฑํ–ˆ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด,
๋ณด์œ  ์ค‘์ธ ์ข…๋ชฉ UserControl์—์„œ ์ข…๋ชฉ A, B๊ฐ€ ์žˆ์„ ๋•Œ (์˜ˆ๋ฅผ ๋“ค์–ด, GridView๋ฅผ ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค)
ํ˜„์žฌ ์ฐจํŠธ UserControl์ด A์— ๋Œ€ํ•œ ์ฐจํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ์„ ๋•Œ, B์ข…๋ชฉ์„ ํด๋ฆญํ•˜๋ฉด ์ฐจํŠธ๋„ B์ข…๋ชฉ์œผ๋กœ ๋™๊ธฐํ™”๊ฐ€ ๋˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•จ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

1๊ฐœ์˜ ์ข‹์•„์š”
interface IChartItemChangedPublisher
{
   event EventHandler<ChartItem> ChartItemChanged {get; }
}

partial class ItemsControl : IChartItemChangedPublisher
{
   public event EventHandler<ChartItem> ChartItemChanged {get; } = delegate { };
   // ...
   ChartItem? _currentItem;
   void OnItemSelected(object? sender, EventArgs e)
   {
      ChartItem item = // ...
      if (_currenItem != item)
      {
         _currentItem = item;
         ChartItemChanged.Invoke(item);
      }
   }
}

partial class ChartControl : IDisposable
{
   public ChartControl(IChartItemChangedPublisher publisher)
   {
      // IDisposable ์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์„ ๋•Œ
      // publisher.ChartItemChanged -= OnChartItemChanged;
      publisher.ChartItemChanged += OnChartItemChanged;   
   }

   void OnChartItemChanged(object? sender, ChartItem item)
   {
      // ...
   }
   public void Dispose() => 
      publisher.ChartItemChanged -= OnChartItemChanged;
}
1๊ฐœ์˜ ์ข‹์•„์š”