첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

■ ICommand 인터페이스 : 대리자 명령 사용하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


DelegateCommand.cs

 

 

using System;

using System.Diagnostics;

using System.Runtime.CompilerServices;

using System.Threading.Tasks;

using System.Windows;

using System.Windows.Input;

using System.Windows.Threading;

 

namespace TestProject

{

    /// <summary>

    /// 대리자 명령

    /// </summary>

    public class DelegateCommand : ICommand

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Event

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

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

 

        /// <summary>

        /// 실행 가능 여부 변경시 이벤트

        /// </summary>

        public event EventHandler CanExecuteChanged

        {

            add => CommandManager.RequerySuggested += value;

            remove => CommandManager.RequerySuggested -= value;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 잠금 객체

        /// </summary>

        private readonly object lockObject = new object();

 

        /// <summary>

        /// 실행 액션

        /// </summary>

        private readonly Action<object> executeAction;

 

        /// <summary>

        /// 실행 가능 여부 함수

        /// </summary>

        private readonly Func<object, bool> canExecuteFunc;

 

        /// <summary>

        /// 실행 여부

        /// </summary>

        private bool isExecuting;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

        

        #region 실행 여부 - IsExecuting

 

        /// <summary>

        /// 실행 여부

        /// </summary>

        public bool IsExecuting

        {

            get

            {

                lock(this.lockObject)

                {

                    return this.isExecuting;

                }

            }

            private set

            {

                lock(this.lockObject)

                {

                    this.isExecuting = value;

                }

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

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

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="executeAction">실행 액션</param>

        /// <param name="canExecuteFunc">실행 가능 여부 함수</param>

        public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecuteFunc)

        {

            if(executeAction == null)

            {

                throw new ArgumentNullException(nameof(executeAction));

            }

 

            this.canExecuteFunc = canExecuteFunc;

 

            this.executeAction = parameter =>

            {

                bool canExecute = this.canExecuteFunc?.Invoke(parameter) ?? true;

 

                if(canExecute)

                {

                    executeAction(parameter);

                }

            };

        }

 

        #endregion

        #region 생성자 - DelegateCommand(executeAction)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="executeAction">실행 액션</param>

        public DelegateCommand(Action<object> executeAction) : this(executeAction, null)

        {

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

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

 

        /// <summary>

        /// 실행 가능 여부 구하기

        /// </summary>

        /// <param name="parameter">매개 변수</param>

        /// <returns>실행 가능 여부</returns>

        [DebuggerStepThrough]

        public bool CanExecute(object parameter)

        {

            if(IsExecuting)

            {

                return false;

            }

 

            return this.canExecuteFunc == null || this.canExecuteFunc(parameter);

        }

 

        #endregion

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

 

        /// <summary>

        /// 실행 가능 여부 구하기

        /// </summary>

        /// <returns>실행 가능 여부</returns>

        public bool CanExecute() => CanExecute(null);

 

        #endregion

        #region 비동기 실행하기 - ExecuteAsync(parameter)

 

        /// <summary>

        /// 비동기 실행하기

        /// </summary>

        /// <param name="parameter">매개 변수</param>

        /// <returns>구성 태스크 대기 가능형</returns>

        public ConfiguredTaskAwaitable ExecuteAsync(object parameter)

        {

            return Task.Run

            (

                (Func<Task>)

                (

                    async () =>

                    {

                        if(IsExecuting)

                        {

                            return;

                        }

 

                        try

                        {

                            IsExecuting = true;

 

                            await Application.Current.Dispatcher.BeginInvoke

                            (

                                this.executeAction,

                                DispatcherPriority.Normal,

                                parameter

                            );

                        }

                        catch(Exception exception)

                        {

                            Debug.WriteLine($"Could not execute command. {exception.Message}");

 

                            throw;

                        }

                        finally

                        {

                            IsExecuting = false;

 

                            CommandManager.InvalidateRequerySuggested();

                        }

                    }

                )

            ).ConfigureAwait(true);

        }

 

        #endregion

        #region 비동기 실행하기 - ExecuteAsync()

 

        /// <summary>

        /// 비동기 실행하기

        /// </summary>

        /// <returns>구성 태스크 대기 가능형</returns>

        public ConfiguredTaskAwaitable ExecuteAsync() => ExecuteAsync(null);

 

        #endregion

        #region 실행하기 - Execute(parameter)

 

        /// <summary>

        /// 실행하기

        /// </summary>

        /// <param name="parameter">매개 변수</param>

        public void Execute(object parameter) => ExecuteAsync(parameter);

 

        #endregion

        #region 실행하기 - Execute()

 

        /// <summary>

        /// 실행하기

        /// </summary>

        public void Execute() => ExecuteAsync(null);

 

        #endregion

    }

}

 

 

MainWindow.xaml

 

 

<Window x:Class="TestProject.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="800"

    Height="600"

    Title="ICommand 인터페이스 : 대리자 명령 사용하기"

    FontFamily="나눔고딕코딩"

    FontSize="16">

    <Grid>

        <StackPanel

            HorizontalAlignment="Center"

            VerticalAlignment="Center">

            <Button

                HorizontalAlignment="Center"

                Margin="10"

                Width="100"

                Height="30"

                Command="{Binding RunCommand}"

                Content="테스트" />

            <ListBox Name="listBox"

                HorizontalAlignment="Center"

                Margin="10"

                Width="300"

                Height="300" />

        </StackPanel>

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

 

 

using System;

using System.Windows;

using System.Threading.Tasks;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public partial class MainWindow : Window

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 실행 명령

        /// </summary>

        private DelegateCommand runCommand;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 실행 명령 - RunCommand

 

        /// <summary>

        /// 실행 명령

        /// </summary>

        public DelegateCommand RunCommand => this.runCommand ??

        (

            this.runCommand = new DelegateCommand

            (

                async parameter =>

                {

                    this.listBox.Items.Add($"[{DateTime.Now.ToString("HH:mm:ss")}] 버튼을 클릭했습니다.");

 

                    await Task.Delay(3000);

 

                    this.listBox.Items.Add($"[{DateTime.Now.ToString("HH:mm:ss")}] 작업을 실행했습니다.");

                }

            )

        );

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

 

            DataContext = this;

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

728x90
반응형
Posted by 사용자 icodebroker
TAG , ,

댓글을 달아 주세요