Event




이벤트(Event)를 정의해 본다면, 내가 만든 어플리케이션과 사용자간의 상호작용 이라고 할 수 있다. 이벤트는 Delegate 를 이용하는 기술로서 .NET의 시스템 이벤트 외에 사용자가 이벤트를 정의해서 사용 할 수도 있다.


※ 이벤트 완성을 위한 3가지 구성 요소
1. 이벤트 소스(이벤트 발생 주체 object)
2. 이벤트 종류 (Click, ...)
3. 이벤트 핸들러 (Button_Click, ... ) : 이벤트 핸들러는 Delegate 이다.


이벤트 핸들러는 포인터 개념을 갖는다.
따라서 하나의 이벤트 핸들러에 여러개의 핸들러를 연결 시킨다면 문제를 유발할 소지가 있다.

이벤트 핸들러는 동일한 시그내처를 가지고 있다
void 리턴형, object 인수(이벤트 발생 주체), 이벤트 인수(이벤트 인수는 이벤트 마다 다르다)



단, 사용자 정의 이벤트 핸들는 사용자가 정의 한다.


< 이벤트 사용 예 >
namespace EventDemo_1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            button1.Text = "이벤트 데모";
        }


        public void SetColor(object sender, EventArgs e)
        {
            button1.BackColor = Color.Blue;
        }


        public void SetLocation(object sender, EventArgs e)
        {
            button1.Location = new Point(50, 200);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;

            MessageBox.Show(btn.Text + "이벤트 발생");
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            // 이벤트 종류 인자가 틀리다.
            // MouseEventArgs 의 부모는 EventArgs 이다.
            button1.Location = e.Location;
        }
    }
}

< 예제 소스 >














※ 사용자 정의 이벤트 규칙!!
1. 선언
2. 연결
3. 발생

선언과 발생은 이벤트 소스(이벤트 발생 주체)에 작성한다. 연결은 이벤트를 사용하는 외부에 작성하게 된다.




다음 예제를 보자.

사용자 정의 이벤트를 선언하는 MyAdd 클래스를 다음과 같이 구현한다.
MyAdd.cs 파일에 작성

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace CustomEvent
{
    // 사용자 정의 이벤트 핸들러(델리게이트) 정의
    // public delegate void MyAddEventHandler(int num);

    // 사용자 정의 이벤트 인자 이벤트 핸들러 정의
    public delegate void MyAddEventHandler(MyEventArgs e);

    public class MyAdd
    {
        // 사용자 정의 이벤트 선언
        public event MyAddEventHandler AddEvent;

        public int AddTo(int i, int j)
        {
            int num = i + j;

            if (num > 100)
            {
                // 이벤트 발생
                // AddEvent(num);

                //
                MyEventArgs e = new MyEventArgs();
                e.num = num;
                e.BackColor = Color.Brown;
                AddEvent(e);
            }

            return num;
        }
    }
}

규칙 "선언은 이벤트 발생 주체에서"  와 같이 MyAdd 클래스에서 선언해 주었다. 사용자 정의 이벤트 에서 선언해 주어야 하는 것은 두가지 이다.

사용자 정의 이벤트 선언
1. 사용자 정의 이벤트
2. 사용자 정의 이벤트와 연결할 이벤트 핸들러

이벤트 핸들러는 delegate 이기 때문에 delegate 로 선언해 준다.
사용자 정의 이벤트 선언은 규칙이 있다. 위에서는 event 와 이벤트 핸들러 그리고 사용할 이벤트 명을 작성해 주었다.

보통 이벤트 핸들러의 인수는 한가지 데이터 타입으로 해도 되지만 인수로 전달할 데이터가 많다면 EventArgs 를 상속받는 사용자 정의 클래스를 정의해서 전달해 주면 된다. EventArgs 를 상속하는 이유는 대부분의 이벤트 핸들러가 EventArgs 를 인수로 갖거나 인수 타입의 부모 클래스로 갖기 때문에 다형성을 이용할 수 있기 때문이다.

EventArgs 를 상속받는 MyEventArgs 클래스. 이 클래스에 원하는 만큼의 데이터를 정의 해주면 된다.

namespace CustomEvent
{
    public class MyEventArgs : EventArgs
    {
        public int num;
        public Color BackColor;
    }
}


이벤트를 사용하는 곳에서는 이벤트 발생을 유도 한다.
이벤트는 이벤트 주체에서 일어나는 것이다.

namespace CustomEvent
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MyAdd obj = new MyAdd();

            // 사용자 정의 이벤트 연결
            // obj.AddEvent += new MyAddEventHandler(obj_AddEvent);
            obj.AddEvent += new MyAddEventHandler(obj_AddEvent);

            int num = obj.AddTo(int.Parse(textBox1.Text), int.Parse(textBox2.Text));
            MessageBox.Show(num.ToString());
        }

        void obj_AddEvent(MyEventArgs e)
        {
            textBox1.Text = e.num.ToString();
            textBox1.BackColor = e.BackColor;
        }

        void obj_AddEvent(int num)
        {
            MessageBox.Show("100보다 큰 결과 입니다. " + num);
        }
    }
}


< 실행 결과>









※ 사용자 정의 이벤트 활용 예제

메인 윈폼에서 새로운 윈폼을 호출한다.(Modal)
새로운 윈폼에서 입력한 데이터가 새로운 윈폼이 종료 되기 전에 메인 윈폼으로 전달되어 메인 윈폼의 데이터를 변경 및 출력 하는 예제 이다.

< 실행 예 >


새로운 윈폼(Form2) 에서 TextBox 에 시작 폴더 이름을 입력한다. 그런 후 button1 을 누르면 해당 데이터가 메인 윈폼(Form1)에 전달되고, C:\ 아래 해당 문자로 시작하는 폴더 이름을 GridView 에 출력 한다.


< MyPopupEventHandler.cs >
사용자 정의 이벤트 핸들러 정의
namespace PopupDemo_3
{
    public delegate void MyPopupEventHandler(string message);
    
}


< Form2.cs >
이벤트를 발생하는 주체에 이벤트를 선언한다. 즉, Form2에서 값이 입력하면 이벤트를 발생 시켜 Form1에 데이터를 전송한다.
namespace PopupDemo_3
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        // 이벤트 선언
        public event MyPopupEventHandler PopupEvent;

        private void button1_Click(object sender, EventArgs e)
        {
            //  이벤트 발생
            PopupEvent(textBox1.Text);
        }
    }
}


< Form1.cs >
이벤트를 통하여 데이터를 받는다. Form2 를 생성할 때 Form2의 이벤트에 자신의 메소드를 이벤트 핸들러로 등록한다.
namespace PopupDemo_3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 obj = new Form2();
            obj.PopupEvent += new MyPopupEventHandler(obj_PopupEvent);
            obj.ShowDialog();
        }

        void obj_PopupEvent(string message)
        {
            textBox1.Text = message;

            // 그리드에  c:\의 폴더를 출력
            DirectoryInfo di = new DirectoryInfo("c:\\");
            
            // 배열이라는 컬렉션을 리턴하는 것에는  LINQ 사용 가능
            var query = from f in di.GetDirectories()
                        where f.Name.StartsWith(message)
                        select f;

            dataGridView1.DataSource = query.ToList();
        }
    }
}


< 소스 파일 >
Posted by six605
,