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개의 좋아요