실전 취소 가능한 버튼 컨트롤 만들기
 
Umc.Core.EventHandlerDictionary 클래스
이 클래스는 Umc.Core 프로젝트에 포함된 클래스 입니다. 이 클래스의 이름에서 알 수 있듯이 이벤트를 사전(Dictionary)로 관리하도록 하기 위한 클래스 입니다.
 
namespace Umc.Core
{
        ///<summary>
        /// Umc.Core<br/>
        /// Delegate 담는 EventHandlerDictionary 컬렉션
        ///</summary>
        public class EventHandlerDictionary : IDisposable
        {
               ///<summary>
               /// Umc.Core<br/>
               /// Event 담는컬렉션
               ///</summary>
               private Dictionary<object,Delegate> eventDictionary = new Dictionary<object,Delegate>();
 
               ///<summary>
               /// Umc.Core<br/>
               /// EventHandlerDictionary EventHandler 추가한다.
               ///</summary>
               ///<param name="key">키값</param>
               ///<param name="value">Delegate</param>
               public void AddHandler(object key, Delegate value)
               {
                       if ( eventDictionary.ContainsKey(key) )
                       {
                              eventDictionary[key] = Delegate.Combine(eventDictionary[key], value);
                       }
                       else
                       {
                              eventDictionary[key] = value;
                       }
               }
 
               ///<summary>
               /// Umc.Core<br/>
               /// EventHandlerDictionary EventHandler 제거한다.
               ///</summary>
               ///<param name="key">키값</param>
               ///<param name="value">Delegate</param>
               public void RemoveHandler(object key, Delegate value)
               {
                       if ( eventDictionary.ContainsKey(key) )
                       {
                              eventDictionary[key] = Delegate.Remove(eventDictionary[key], value);
                       }
               }
 
               public bool Contains(object key)
               {
                       return this.eventDictionary.ContainsKey(key);
               }
 
               ///<summary>
               /// Umc.Core<br/>
               /// EventHandlerDictionary 인덱서
               ///</summary>
               ///<param name="key"></param>
               ///<returns></returns>
               public Delegate this[object key]
               {
                       get { return eventDictionary[key]; }
                       set { eventDictionary[key] = value; }
               }
 
               #region IDisposable 멤버
               ///<summary>
               /// Umc.Core<br/>
                /// EventHandlerDictionary 자원을해제한다.
               ///</summary>
               public void Dispose()
               {
                       if( eventDictionary != null )
                              eventDictionary.Clear();
 
                       eventDictionary = null;
               }
               #endregion
        }
}
 
클래스 내부에는 Dictionary 제네릭 클래스의 오브젝트를 생성하여, AddHandler(), RemoveHandler() 를 통해 이벤트를 사전에 추가/삭제 하는 로직이 들어있습니다.
 
 
ButtonEx 네임스페이스
Click 이벤트 전/후에 발생할 이벤트의 인자를 전달한 EventArgs 클래스 입니다. 이미 지난 회차를 보신 분이라면 그렇게 생소하지 않을 것입니다.
///<summary>
/// Before 이벤트가발생할전달될이벤트인자클래스입니다.
///</summary>
public class BeforeClickEventArgs : CancelEventArgs
{
        public string Reason { get; set; }
}
 
///<summary>
/// After 이벤트가발생할전달될이벤트인자클래스입니다.
///</summary>
public class AfterClickEventArgs : EventArgs { }
 
또한, 직관적인 코딩을 위해 Before/After 이벤트를 위한 델리게이트를 선언하였습니다. 특별한 변경된 EventArgs 와 같은 인자가 없다면 기존 EventHandler 를 활용해도 되지만, 언제든 추후에 확장될 가능성은 충분하다고 생각합니다. 그렇기 때문에 델리게이트를 선언해 주었답니다.
///<summary>
/// BeforeClick 이벤트를캡슐화하는델리게이트입니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
public delegate void BeforeClickEventHandler(object sender, BeforeClickEventArgs e);
///<summary>
/// AfterClick 이벤트를캡슐화하는델리게이트입니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
public delegate void AfterClickEventHandler(object sender, AfterClickEventArgs e);
 
여기서 이벤트는 사전(Dictionary) 을 통해 이벤트를 관리하게 됩니다. Umc.Core 프로젝트에 사용되는 EventHandlerDictionary 클래스의 일부를 직접 예제 클래스에 포함한 것입니다. 이 EventHandlerDictionary 에 접근하기 위한 Events 프로퍼티를 선언하였습니다.
private EventHandlerDictionary events;
///<summary>
/// EventHandlerDictionary 통해이벤트를관리합니다.
///</summary>
protected EventHandlerDictionary Events
{
        get
        {
               if( events == null )
                       events = new EventHandlerDictionary();
 
               return events;
        }
}
 
여기에서 선언된 이벤트는 EventHandlerDictionary 클래스에서 관리하게 될 것이기 때문에, event 선언에 대해 커스트마이징(?)이 필요합니다. 즉, 이벤트의 추가/삭제에 대한 액션을 변경할 필요가 있습니다.
private object EVENT_BEFORE_CLICK     = new object(); // BeforeClick 이벤트오브젝트
private object EVENT_AFTER_CLICK      = new object(); // AfterClick 이벤트오브젝트
 
///<summary>
/// BeforeClick 이벤트입니다. Click 이벤트가발생하기전에발생합니다.
///</summary>
[Description("Click 이벤트가발생하기전에발생합니다")]
public event BeforeClickEventHandler BeforeClick
{
        add
        {
               this.Events.AddHandler(EVENT_BEFORE_CLICK, value);
        }
        remove
        {
               this.Events.RemoveHandler(EVENT_BEFORE_CLICK, value);
        }
}
 
///<summary>
/// AfterClick 이벤트입니다. Click 이벤트가발생한발생합니다.
///</summary>
[Description("Click 이벤트가발생후에발생합니다")]
public event AfterClickEventHandler AfterClick
{
        add
        {
               this.Events.AddHandler(EVENT_AFTER_CLICK, value);
        }
        remove
        {
               this.Events.RemoveHandler(EVENT_AFTER_CLICK, value);
        }
}
 
여기는 각각의 Before/After 이벤트를 발생하는 메서드와 CancelEventArgs 의 Cancel 프로퍼티를 검사하는 메서드가 존재합니다. OnEventsFire() 메서드를 눈여겨 보시면 될 것 같습니다.
///<summary>
/// BeforeClick 이벤트를발생합니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
protected virtual void OnBeforeClick(object sender, BeforeClickEventArgs e)
{
        if( !this.Events.Contains( EVENT_BEFORE_CLICK ) ) return;
 
        BeforeClickEventHandler handler       =
this.Events[ EVENT_BEFORE_CLICK ] as BeforeClickEventHandler;
        if( handler != null )
               handler(sender, e);
}
 
///<summary>
/// AfterClick 이벤트를발생합니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
protected virtual void OnAfterClick(object sender, AfterClickEventArgs e)
{
        if( !this.Events.Contains(EVENT_AFTER_CLICK) ) return;
 
        AfterClickEventHandler handler =
this.Events[ EVENT_AFTER_CLICK ] as AfterClickEventHandler;
        if( handler != null )
               handler(sender, e);
}
 
///<summary>
/// Click 이벤트가발생할경우 BeforeClick/AfterClick 이벤트를발생합니다.
///</summary>
///<param name="sender"></param>
protected virtual void OnEventsFire( object sender )
{
        BeforeClickEventArgs beforeArgs       = new BeforeClickEventArgs();
        OnBeforeClick( sender, beforeArgs );
 
        if( beforeArgs.Cancel ) return;
 
        AfterClickEventArgs afterArgs = new AfterClickEventArgs();
        OnAfterClick( sender, afterArgs );
}
 
[Obsolete("ButtonEx 컨트롤에서는 Click 이벤트를사용하지않도록합니다. 대신 AfterClick 이벤트를사용하세요")]
protected override void OnInit(EventArgs e)
{
        base.OnInit(e);
        this.Click += new EventHandler(ServerControl1_Click);
}
 
private void ServerControl1_Click(object sender, EventArgs e)
{
        OnEventsFire(sender);
}
 
이제 간략한 소스 코드 설명은 끝났네요. 힘들게 만든 ButtonEx 서버 컨트롤을 어떻게 활용하면 될지 다음 회차를 참고하세요.
저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by 땡초 POWERUMC
TAG ,

댓글을 달아 주세요