White Whale Studio

[MVC Pattern] Winform 예제 본문

IT Engineering/C#.net

[MVC Pattern] Winform 예제

glorymind 2016. 6. 21. 11:22
반응형

이전에 포스팅 했었던 MVC Pattern을 활용하여 Winform으로 구현한 예제가 있어 살펴보도록 하겠습니다.


원본 소스는 아래의 링크를 참조하시기 바랍니다.



혹시나 링크가 잘리는 경우를 대비하여 아래의 원본 소스파일을 첨부했습니다.

MVCTest_Source.zip


실행 화면은 아래와 같습니다.

프로그램의 기능은 단순합니다. 버튼을 클릭하면 텍스트박스에 숫자를 1 증가시켜줍니다.

사용자가 직접 텍스트박스에 숫자를 입력하는 경우에는 입력한 숫자를 기준으로 1을 증가시킵니다.





Controller - View - Model 순서로 알아보고 관련된 소스 및 Form의 소스를 보면서 살펴보겠습니다.


우선 Controller를 살펴보겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    // IController Interface 는 오직 값 증가 기능만을 제공합니다.
    public interface IController
    {
        void incvalue();
    }
 
    public class IncController : IController
    {
        IView view;
        IModel model;
 
        // IController를 구현하는 해당 컨트롤러는 뷰와 모델을 연결시키고        
        // View에 IModel Interface를 통해서 view_changed 이벤트 핸들러를 더합니다.
        // 이를 통해 View는 컨트롤러와 연결됩니다.
        public IncController(IView v, IModel m)
        {
            view = v;
            model = m;
            view.setController(this);
            model.attach((IModelObserver)view);
            view.changed += new ViewHandler<IView>(this.view_changed);            
        }
 
        // 사용자가 값을 변화시킬 때 뷰로부터 이벤트가 발생됩니다.
        public void view_changed(IView v, ViewEventArgs e)
        {
            model.setvalue(e.value);
        }
 
        // 해당 메서드가 실제적으로 모델이 하는 일입니다.
        public void incvalue()
        {
            model.increment();
        }
 
    }
cs

주석을 참고하시기 바랍니다.

간략적인 설명을 더하자면, Controller에서 View와 Model을 연결하고 view에서 발생하는 이벤트를 받도록 설정하고(21 line)

받은 이벤트를 통해 모델로 전달하기 위한 연결을 수행합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
         public delegate void ViewHandler<IView>(IView sender, ViewEventArgs e);
 
        // The event arguments class that will be used while firing the events
        // for this program, we have only one value which the user changed.
        //
        // 해당 이벤트 인수는 해당 프로그램을 위해서 이벤트가 발생될때 사용됩니다.
        // 여기서 사용자가 변경할 수 있는 값은 오직 하나입니다.
        public class ViewEventArgs: EventArgs 
        {
            public int value;
            public ViewEventArgs(int v) { value = v; }
        }
    
        // Currently, the interface only contains the method to set the controller to which
        // it is tied. The rest of the view related code is implemented in the form.
        
        // Controller와의 연결을 위한 용도
        // 현재, 해당 인터페이스는 오직 이것과 연결된 컨트롤러 설정을 위한 메서드를 포함하고 있습니다.
        // 나머지 뷰와 관련된 코드들은 폼 내부에서 구현됩니다.
        public interface IView
        {
            event ViewHandler<IView> changed;
            void setController(IController cont);
        }
cs


위의 소스는 IView와 이벤트 처리를 위한 클래스입니다. 

뷰 클래스에 있는 인터페이스는 실제로는 Form에서 구현이 됩니다. 

보시는 것과 같이 해당 소스에는 뷰가 변경 되었을 때 이벤트 핸들러와 컨트롤러를 설정하는 부분만 포함됩니다.



다음은 모델과 관련된 소스입니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    public delegate void ModelHandler<IModel>(IModel sender, ModelEventArgs e);
    
    // ModelEventArgs 클래스는 값 변화시에 컨트롤러에 값을 전달해줍니다.
    public class ModelEventArgs : EventArgs
    {
        public int newval;
        public ModelEventArgs(int v) 
        { 
            newval = v; 
        }
    }
 
    // Form/View의 인터페이스는 이와 같이 구현해야합니다. 
    // 모델 내에서 값이 변화될 때 이벤트가 발생합니다.
    public interface IModelObserver
    {
        void valueIncremented(IModel model, ModelEventArgs e);
    }
 
    // 우리가 함수에 추가했던 모델 인터페이스는 값을 변경될 때 알려줍니다.
    // 실제 데이터 처리 함수는 값이 증가될 때 증가시킵니다 
    // setValue 함수는 텍스트박스에 있는 값을 사용자가 변경할 때 설정용으로 사용합니다.
    public interface IModel
    {
        void attach(IModelObserver imo);
        void increment();
        void setvalue(int v);
    }
 
    public class IncModel : IModel
    {
        public event ModelHandler<IncModel> changed;
        int value;
 
        // IModel 인터페이스의 구현은 초기값을 0으로 설정하는 것입니다.
        public IncModel() 
        { 
            value = 0
        }
 
        // setvalue 메서드는 사용자가 텍스트 박스에 있는 값을 직접 변경할 경우에 사용합니다.
        //또한 컨트롤러 내에서 뷰 변경 이벤트가 발생할때도 입니다.
        public void setvalue(int v) 
        { 
            value = v; 
        }
 
        public static delegate void OnIncHandler(int i);
 
        // 값 변경과 새 값에 대한 이벤트 발생은 ModelEventArgs 내부에 있습니다.
        // 이것은 모델 내부에 있는 valueIncremented 함수를 호출하고 추후에 텍스트 박스에 표시할것입니다.
        public void increment() 
        { 
            value++
            changed.Invoke(thisnew ModelEventArgs(value));
        }
 
        // attach 함수는 IModelObserver의 구현이며 이것은 값이 변경될때 알려줄 수 있습니다.
        public void attach(IModelObserver imo) 
        { 
            changed += new ModelHandler<IncModel>(imo.valueIncremented);
        }
 
    }
cs


모델은 컨트롤러로부터 전달된 숫자를 증가시키는 비지니스 로직을 다룹니다. 또한 변경된 데이터 값을 뷰에 전달합니다.

폼(View)에서는 IModelObserver를 구현하여 모델에서 전달받는 데이터를 화면에 출력합니다.


1
2
3
4
5
6
        /// 해당 이벤트는 IModelObserver의 구현입니다.
        /// 즉, 모델 단계에서 전달받는 데이터를 적용하는 부분
        public void valueIncremented(IModel m, ModelEventArgs e)
        {
            textBox1.Text = "" + e.newval;
        }
cs


아래의 소스는 Model - View - Controller를 한데 묶어주는 소스입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace MVCTest
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
 
            /* 새로운 폼에서 뷰, 모델, 컨트롤러 객체를 스스로 생성하고 설명을 달아보세요.
             * 콘크리트 구현인 IncController를 포함한 컨트롤러를 생성하고 뷰와 모델로 전달합니다.
             * 컨트롤러는 생성자 내에 포함된 연관된 모델과 뷰에 저장할 것입니다.
             * 폼 내부에 있는 뷰는 해당 단계에서 자동적으로 컨트롤러와 연결됩니다.
             * 당신에 의해 생성되는 뷰 객제는 사실은 폼입니다.
             */
            IModel mdl = new IncModel(); // IModel 상속받는 IncModel 객체
            Form1 view = new Form1();  // IView 상속받으므로 View 역할            
            IController cnt = new IncController(view,mdl); // IController로 전달해서 Model - View - Controller 연결
            Application.Run(view);
        }
    }
}
cs



다음은 폼(Form)의 소스입니다.


실제적으로 보여지는 View이며 IView를 상속받아서 setController를 구현합니다. 이를 통해 View와 Controller가 연결됩니다.


어떤 연산이든 모델이 필요합니다. 이것은 컨트롤러를 사용하여 모델에 신호를 줄것이구요.

버튼을 클릭하게 되면, 컨트롤러는 값을 증가시켜달라고 컨트롤러에게 요청합니다. 또한 사용자가 텍스트박스에 직접 타이핑을 하게되면

view changed event가 발생합니다. 이것을 통해 IModelObserver의 구현인 valueIncremented가 값이 변할 때마다 Model에 의해 invoke 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
   public partial class Form1 : Form, IView, IModelObserver
    {
 
        IController controller;
 
        public event ViewHandler<IView> changed;
 
        // 뷰는 연관된 컨트롤러를 설정할 것입니다. 이것이 뷰가 컨트롤러와 연결하는 방법입니다.
        public void setController(IController cont)
        {
            controller = cont;
        }
        
        public Form1()
        {
            InitializeComponent();
        }
 
        /// 컨트롤러 요청부
        /// 사용자가 버튼을 클릭할 때 컨트롤러에게 값을 증가해달라고 요청합니다.
        /// 이 때 어떻게 하거나 어디서 하는지는 중요하지 않죠
        private void button1_Click(object sender, EventArgs e)
        {
            controller.incvalue();
        }
 
        /// 해당 이벤트는 IModelObserver의 구현입니다.
        /// 즉, 모델 단계에서 전달받는 데이터를 적용하는 부분
        public void valueIncremented(IModel m, ModelEventArgs e)
        {
            textBox1.Text = "" + e.newval;
        }
 
        /// 해당 이벤트가 발생하여 증가할 때는 사용자가 값을 변경할 때입니다.
        private void textBox1_Leave(object sender, EventArgs e)
        {
            try
            {
                changed.Invoke(thisnew ViewEventArgs(int.Parse(textBox1.Text)));
            }
            catch (Exception)
            {
                MessageBox.Show("Please enter a valid number");
            }
        }
    }
cs


위와 같이 MVC Pattern의 구현 예제를 살펴보았습니다.

상세한 내용은 원문이 있는 곳을 참고하시거나 첨부한 소스를 확인하시기 바랍니다.


간략하게 정리해보면

Winform의 경우,


Model -> View에 정보를 전달(전달을 위해 여기서는 Observer를 사용), 컨트롤러로부터 명령 전달 정보를 받음


View -> Interface로 선언되고, 실제적으로 보여지는 구현은 Form에서 완성됨, Model로 부터 전달받은 데이터를 갱신,

           사용자로부터 명령을 컨트롤러로 전달


Controller -> Model과 View에 연결, Model로의 명령 전달을 위한 구현 포함


Form -> View의 실제 구현이며 해당 위치에서 컨트롤러로 값 증가 요청을 수행하고, Model로부터 변경된 값을 받아 화면에 출력함.


위와 같습니다.


     



반응형

'IT Engineering > C#.net' 카테고리의 다른 글

EventArgs  (0) 2016.06.23
StyleCop - Coding Guide / 스타일콥 코드 분석기 for C#  (0) 2016.06.22
[MVC Pattern] 개념 정리  (2) 2016.06.21
Visual Studio 2010 C# & Nunit 설정법  (0) 2016.06.13
Mybatis.Net & Sqlite3  (0) 2016.06.09
Comments