첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

▶ DelegateCommand.cs

using System;
using System.Collections.Generic;
using System.Windows.Input;

/// <summary>
/// 대리자 명령
/// </summary>
/// <typeparam name="TParameter">매개 변수 타입</typeparam>
public class DelegateCommand<TParameter> : ICommand
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Event
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 실행 가능 여부 변경시 이벤트 - CanExecuteChanged

    /// <summary>
    /// 실행 가능 여부 변경시 이벤트
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add
        {
            CommandManager.AddWeakReferenceHandler(ref this.weakReferenceList, value);
        }
        remove
        {
            CommandManager.RemoveWeakReferenceHandler(this.weakReferenceList, value);
        }
    }

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Private

    #region Field

    /// <summary>
    /// 실행 액션
    /// </summary>
    private readonly Action<TParameter> executeAction;


    /// <summary>
    /// 실행 가능 여부 함수
    /// </summary>
    private readonly Func<TParameter, bool> canExecuteFunction;

    /// <summary>
    /// 약한 참조 리스트
    /// </summary>
    private List<WeakReference> weakReferenceList;

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 생성자 - DelegateCommand(executeAction, canExecuteFunction)

    /// <summary>
    /// 생성자
    /// </summary>
    /// <param name="executeAction">실행 액션</param>
    /// <param name="canExecuteFunction">실행 가능 여부 함수</param>
    public DelegateCommand(Action<TParameter> executeAction, Func<TParameter, bool> canExecuteFunction)
    {
        if(executeAction == null)
        {
            throw new ArgumentNullException("executeAction");
        }

        this.executeAction      = executeAction;
        this.canExecuteFunction = canExecuteFunction;
    }

    #endregion
    #region 생성자 - DelegateCommand(executeAction)

    /// <summary>
    /// 생성자
    /// </summary>
    /// <param name="executeAction">실행 액션</param>
    public DelegateCommand(Action<TParameter> executeAction) : this(executeAction, null)
    {
    }

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 실행 가능 여부 구하기 - CanExecute(parameter)

    /// <summary>
    /// 실행 가능 여부 구하기
    /// </summary>
    /// <param name="parameter">매개 변수</param>
    /// <returns>실행 가능 여부</returns>
    public bool CanExecute(TParameter parameter)
    {
        if(this.canExecuteFunction != null)
        {
            return this.canExecuteFunction(parameter);
        }

        return true;
    }

    #endregion
    #region 실행하기 - Execute(parameter)

    /// <summary>
    /// 실행하기
    /// </summary>
    /// <param name="parameter">매개 변수</param>
    public void Execute(TParameter parameter)
    {
        if(this.executeAction != null)
        {
            this.executeAction(parameter);
        }
    }

    #endregion

    #region 실행 가능 여부 구하기 - ICommand.CanExecute(parameter)

    /// <summary>
    /// 실행 가능 여부 구하기
    /// </summary>
    /// <param name="parameter">매개 변수</param>
    /// <returns>실행 가능 여부</returns>
    bool ICommand.CanExecute(object parameter)
    {
        if(parameter == null && typeof(TParameter).IsValueType)
        {
            return this.canExecuteFunction == null;
        }

        return CanExecute((TParameter)parameter);
    }

    #endregion
    #region 실행하기 - ICommand.Execute(parameter)

    /// <summary>
    /// 실행하기
    /// </summary>
    /// <param name="parameter">매개 변수</param>
    void ICommand.Execute(object parameter)
    {
        Execute((TParameter)parameter);
    }

    #endregion

    #region 실행 가능 여부 변경시 이벤트 발생시키기 - RaiseCanExecuteChangedEvent()

    /// <summary>
    /// 실행 가능 여부 변경시 이벤트 발생시키기
    /// </summary>
    public void RaiseCanExecuteChangedEvent()
    {
        FireCanExecuteChangedEvent();
    }

    #endregion

    ////////////////////////////////////////////////////////////////////////////////////////// Protected

    #region 실행 가능 여부 변경시 이벤트 발생시키기 - FireCanExecuteChangedEvent()

    /// <summary>
    /// 실행 가능 여부 변경시 이벤트 발생시키기
    /// </summary>
    protected virtual void FireCanExecuteChangedEvent()
    {
        CommandManager.CallWeakReferenceHandlers(this.weakReferenceList);
    }

    #endregion
}

 

728x90

 

▶ CommandManager.cs

using System;
using System.Collections.Generic;

/// <summary>
/// 명령 관리자
/// </summary>
public class CommandManager
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Static
    //////////////////////////////////////////////////////////////////////////////// Public

    #region 약한 참조 핸들러 추가하기 - AddWeakReferenceHandler(weakReferenceList, eventHandler)

    /// <summary>
    /// 약한 참조 핸들러 추가하기
    /// </summary>
    /// <param name="weakReferenceList">약한 참조 리스트</param>
    /// <param name="eventHandler">이벤트 핸들러</param>
    public static void AddWeakReferenceHandler(ref List<WeakReference> weakReferenceList, EventHandler eventHandler)
    {
        if(weakReferenceList == null)
        {
            weakReferenceList = new List<WeakReference>();
        }

        weakReferenceList.Add(new WeakReference(eventHandler));
    }

    #endregion
    #region 약한 참조 핸들러 제거하기 - RemoveWeakReferenceHandler(weakReferenceList, eventHandler)

    /// <summary>
    /// 약한 참조 핸들러 제거하기
    /// </summary>
    /// <param name="weakReferenceList">약한 참조 리스트</param>
    /// <param name="eventHandler">이벤트 핸들러</param>
    public static void RemoveWeakReferenceHandler(List<WeakReference> weakReferenceList, EventHandler eventHandler)
    {
        if(weakReferenceList != null)
        {
            for(int i = weakReferenceList.Count - 1; i >= 0; i--)
            {
                WeakReference weakReference = weakReferenceList[i];

                EventHandler existingEventHandler  = weakReference.Target as EventHandler;
                   
                if((existingEventHandler  == null) || (existingEventHandler  == eventHandler))
                {
                    weakReferenceList.RemoveAt(i);
                }
            }
        }
    }

    #endregion
    #region 약한 참조 핸들러 호출하기 - CallWeakReferenceHandlers(weakReferenceList)

    /// <summary>
    /// 약한 참조 핸들러 호출하기
    /// </summary>
    /// <param name="weakReferenceList">약한 참조 리스트</param>
    public static void CallWeakReferenceHandlers(List<WeakReference> weakReferenceList)
    {
        if(weakReferenceList != null)
        {
            EventHandler[] eventHandlerArray = new EventHandler[weakReferenceList.Count];

            int count = 0;

            for(int i = weakReferenceList.Count - 1; i >= 0; i--)
            {
                WeakReference weakReference  = weakReferenceList[i];

                EventHandler eventHandler = weakReference.Target as EventHandler;
                    
                if(eventHandler == null)
                {
                    weakReferenceList.RemoveAt(i);
                }
                else
                {
                    eventHandlerArray[count] = eventHandler;

                    count++;
                }
            }

            for(int i = 0; i < count; i++)
            {
                EventHandler eventHandler = eventHandlerArray[i];

                eventHandler(null, EventArgs.Empty);
            }
        }
    }

    #endregion
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요