레이블이 Command패턴인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Command패턴인 게시물을 표시합니다. 모든 게시물 표시

2021년 11월 21일 일요일

WPF Command 패턴 HelloWorld, CanExecuteChanged , CanExecute, ICommand, WPf학원

 

WPF Command 패턴 HelloWorld, CanExecuteChanged , CanExecute, ICommand, WPf학원


http://ojc.asia/bbs/board.php?bo_table=WPF&wr_id=174 


WPF Command 패턴 HelloWorld, CanExecuteChanged , CanExecute, ICommand

WPF Command 패턴 HelloWorld, CanExecuteChanged , CanExecute, ICommand WPF의 명령(Command)은 ICommand 인터페이스를 구현하여 만들며 ICommand는 Execute 및 CanExecute라는 두 가지 메서드와 CanExecuteChanged 이벤트를 제공한

ojc.asia


https://www.youtube.com/watch?v=Ycb2Tg56l-M&list=PLxU-iZCqT52Cmj47aKB1T-SxI33YL7rYS&index=17&t=3s 

https://www.youtube.com/watch?v=5OEOPCHKR3Q&list=PLxU-iZCqT52Cmj47aKB1T-SxI33YL7rYS&index=18 

  • WPF의 명령(Command)은 ICommand 인터페이스를 구현하여 만들며 ICommand는 Execute 및 CanExecute라는 두 가지 메서드와 CanExecuteChanged 이벤트를 제공한다. 
  • Execute 메서드는 실제 처리해야 하는 작업을 기술하고 CanExecute 메소드에서는 Execute 메소드의 코드를 실행할지 여부를 결정하는 코드를 기술한다. CanExecute가 false를 리턴하면 Execute 메소드는 호출되지 않는다.
  • 즉 CanExecute 메소드는 명령을 사용 가능하게 하거나 사용 불가능하게 할 때 사용되며 명령을 사용할 수 있는지 여부를 확인하기 위해 WPF에 의해 호출된다. 이 메소드는 키보드 GET포커스, LOST포커스, 마우스 업 등과 같은 UI 상호 작용 중에 대부분 발생한다. 
  • CanExecute 메소드가 호출되어 CanExecute의 상태가 변경되면 CanExecuteChanged 이벤트가 발생해야 하며,  WPF는 CanExecute를 호출하고 Command에 연결된 컨트롤의 상태를 변경한다.




  • 1. View(MainWindow.xaml)

<Window x:Class="MVVMTest.MainWindow"

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

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

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:MVVMTest"

        mc:Ignorable="d"

        Title="MainWindow" Height="200" Width="400">

    <Window.DataContext>

        <local:MainWindowViewModel/>

    </Window.DataContext>

    <Grid>

        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="62,45,0,0" TextWrapping="Wrap"

                 Text="" VerticalAlignment="Top" Width="126"/>

        <Button Content="Click" 

                Height="23" 

                HorizontalAlignment="Left" 

                Margin="193,45,0,0" 

                Name="btnClick" 

                VerticalAlignment="Top" 

                Width="87"

                Command="{Binding ButtonCommand}" 

                CommandParameter="{Binding Text, ElementName=textBox}" />    

</Grid>

</Window>


  • 2. ViewModel(C# 클래스)- ViewModel에서 RelayCommand를 통해 메시지박스를 띄움

using System;

using System.Windows.Input;

using System.Windows;


namespace MVVMTest

{

    class MainWindowViewModel

    {

        private ICommand m_ButtonCommand;

        public ICommand ButtonCommand

        {

            get

            {

                return m_ButtonCommand;

            }

            set

            {

                m_ButtonCommand = value;

            }

        }


        public MainWindowViewModel()

        {

            //ButtonCommand = new RelayCommand(new Action<object>(ShowMessage));

            ButtonCommand = new RelayCommand(ShowMessage);


        }


        public void ShowMessage(object param)

        {

            MessageBox.Show("Hi~ " + param.ToString());

        }    }

}



  • ICommand를 상속받은 RelayCommand.cs

using System;

using System.Windows.Input;


namespace MVVMTest

{

    class RelayCommand : ICommand

    {

        private Action<object> _action;


        public RelayCommand(Action<object> action)

        {

            _action = action;

        }


        #region ICommand Members


        public bool CanExecute(object parameter)

        {

            return true;

        }


        public event EventHandler CanExecuteChanged;


        public void Execute(object parameter)

        {

_action(parameter);          

}

        #endregion

    }

}


Command vs Click Event


- Command는 Caller와 연결되어 있지 않으므로 동일한 Command가 메뉴 항목, 도구 모음 버튼, 키보드 등에서 호출 가능

- Command는 명령 상태에 따라 관련된 모든 UI 컨트롤을 활성화 / 비활성화 할 수 있도록 지원(실행 가능 또는 불가능)


#MVVM#COMMAND패턴#WPFCommand#WPFMVVM#MVVM이란#WPF강좌#WPF교육#WPF동영상#WPF학원

MVVM, Command패턴, WPFCommand, WPFMVVM, MVVM이란, WPF강좌, WPF교육, WPF동영상, WPF학원

WPF Command의 이해 및 Command, 데이터바인딩 실습, WPF교육, WPF학원

 

WPF Command의 이해 및 Command, 데이터바인딩 실습, WPF교육, WPF학원

http://ojc.asia/bbs/board.php?bo_table=WPF&wr_id=173 


WPF Command의 이해 및 Command, 데이터바인딩 실습

WPF Command의 이해 및 Command, 데이터바인딩 실습전통적인 이벤트 기반 프로그래밍에서 컨트롤에 이벤트 핸들러 메소드를 코드 비하인드에서 연결하여 사용자의 이벤트를 처리했다. 그러나 이방식

ojc.asia


https://www.youtube.com/watch?v=68nzzq_bew0&list=PLxU-iZCqT52Cmj47aKB1T-SxI33YL7rYS&index=16&t=1s 


https://www.youtube.com/watch?v=OTMyi2XrVyw&list=PLxU-iZCqT52Cmj47aKB1T-SxI33YL7rYS&index=15&t=3s 

  • 전통적인 이벤트 기반 프로그래밍에서 컨트롤에 이벤트 핸들러 메소드를 코드 비하인드에서 연결하여 사용자의 이벤트를 처리했다. 그러나 이방식은 이벤트처리 핸들러를 재사용하거나 단위 테스트를 어렵게 한다.
  • XAML UI에서 버튼을 클릭시 MVVM에서는 Click 이벤트 핸들러를 이용하기 보다는 Commamd를 이용하기를 권장한다. 여러 버튼에서 하나의 Command를 공유할 수 있으므로 모든 컨트롤마다 Click 이벤트를 만드는 방법 보다는 효율적이기 때문이다.
  • WPF의 명령(Command)은 ICommand 인터페이스를 구현하여 만들며 ICommand는 Execute 및 CanExecute라는 두 가지 메서드와 CanExecuteChanged 이벤트를 제공한다. 
  • Execute 메서드는 실제 처리해야 하는 작업을 기술하고 CanExecute 메소드에서는 Execute 메소드의 코드를 실행할지 여부를 결정하는 코드를 기술한다. CanExecute가 false를 리턴하면 Execute 메소드는 호출되지 않는다.
  • 즉 CanExecute 메소드는 명령을 사용 가능하게 하거나 사용 불가능하게 할 때 사용되며 명령을 사용할 수 있는지 여부를 확인하기 위해 WPF에 의해 호출된다. 이 메소드는 키보드 GET포커스, LOST포커스, 마우스 업 등과 같은 UI 상호 작용 중에 대부분 발생한다. 
  • 사용자 정의 명령의 경우 CanExucute 메서드가 대부분의 시나리오에서 호출되지는 않으므로 어떤 조건에 따라 버튼을 활성화, 비활성화 해야 할 수도 있는데 ICommand 구현체에서 CanExecuteChanged 이벤트를 CommandManager의 RequerySuggested 이벤트에 연결하면 된다.
  • CanExecute 메소드가 호출되어 CanExecute의 상태가 변경되면 CanExecuteChanged 이벤트가 발생해야 하며,  WPF는 CanExecute를 호출하고 Command에 연결된 컨트롤의 상태를 변경한다.


// CanExecuteChanged 이벤트는 해당 ICommand에 바인딩 된 

// 모든 명령 소스(예 : Button 또는 MenuItem)에 

// CanExecute에 의해 반환 된 값이 변경 되었음을 알린다.


// 커맨드 소스는 일반적으로 상태를 적절히 업데이트해야 하는데

// 예를 들면 CanExecute()가 false를 반환하면 버튼이 비활성화 된다).


// CommandManager.RequerySuggested 이벤트는 CommandManager가 명령 실행에 

// 영향을 줄 수있는 변경 사항이 있다고 생각할 때마다 발생하며 이때마다 

// CanExecute가 호출된다.


// 예를 들어, 이는 포커스의 변화 일 수 있는데. 이 이벤트가 많이 발생한다.

// 따라서 본질적으로 이 코드의 역할은 CommandManager가 명령 실행 기능이 변경되었다고 생각할 때마다(실제로 변경되지 않은 경우에도) CanExecuteChanged를 발생시키는 것이다.

public event EventHandler CanExecuteChanged

{

            add { CommandManager.RequerySuggested += value; }

            remove { CommandManager.RequerySuggested -= value; } 

}

  • CommandManager.RequerySuggested 이벤트는 CanExecute 메서드를 강제로 실행할 수 있다. 
  • CanExecuteChanged 이벤트는 CommandManager의 RequerySuggested에 위임되어 모든 종류의 UI 상호작용을 통해 변경사항이 호출되는 정확한 알림을 제공한다.
  • RequerySuggested 이벤트의 CommandManager.InvalidateRequerySuggested()를 호출하여 CommandManager의 RequerySuggested 이벤트를 발생하도록 할 수도 있는데 다음 예제를 참조 하자.
  • Command 패턴에서는 몇가지 주체가 있는데 서비스를 요청하는 클라이언트(손님), 명령을 서술하는 Command Object(주문서), 명령을 요청하는 Command Invoker(웨이터), 특정 명령을 실제 처리하는 Command Receiver(Target, 요리사)가 있다.

[먼저 간단한 예제를 만들고 이해를 해보자.] 

  • 프로젝트 명 : CommandExam
  • [실행화면]
  • Model : [Emp.cs]

namespace CommandExam

{

    class Emp

    {

        public string Ename { getset; }

        public string Job { getset; }

public override string ToString()

        {

            return "[" + Ename + "," + Job + "]";

        }

    } 

}


  • Command Object : [RelayCommand.cs]



using System;

using System.Windows.Input;


namespace CommandExam

{

    class RelayCommand : ICommand

    {

        #region Variables

        Func<object, bool> canExecute;

        Action<object> executeAction;     

        #endregion


        #region Construction/Initialization

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

        {

        }


        public RelayCommand(Action<object> executeAction, Func<objectbool> canExecute)

        {

            //if (executeAction == null) throw new ArgumentNullException("Execute Action was null for ICommanding Operation.");

            //this.executeAction = executeAction;

            this.executeAction = executeAction ?? throw new ArgumentNullException("Execute Action was null for ICommanding Operation.");

            this.canExecute = canExecute;

        }

        #endregion


        #region ICommand Member

//CommandManager.RequerySuggested 이벤트가 호출될 때마다 실행

//즉 CanExecuteChanged 이벤트가 호출될 때마다 실행

        public bool CanExecute(object param)

        {

            // 사원이름을 입력하지 않으면 Add 버튼은 비활성화 된다.

            if (param?.ToString().Length == 0) return false;

            bool result = this.canExecute == null ? true : this.canExecute.Invoke(param);

            return result;

        }


        public void Execute(object param)

        {

            //System.Windows.MessageBox.Show(param.ToString());

            this.executeAction.Invoke(param);

        }

        public event EventHandler CanExecuteChanged

        {

            add { CommandManager.RequerySuggested += value; }

            remove { CommandManager.RequerySuggested -= value; }

        }

        #endregion

    }

}


  • Command Receiver : [MainWindowViewModel]


using System.Collections.ObjectModel;

using System.ComponentModel;

using System.Runtime.CompilerServices;


namespace CommandExam

{

    class MainWindowViewModel : INotifyPropertyChanged

    {

        public Emp _SelectedEmp;

        public Emp SelectedEmp

        {

            get

            {

                return _SelectedEmp;

            }

            set

            {

                _SelectedEmp = value;

                OnPropertyChanged("SelectedEmp");

            }

        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string Pname = null)

        {

            PropertyChanged?.Invoke(thisnew PropertyChangedEventArgs(Pname));

        }


        public RelayCommand AddEmpCommand { getset; }


// 항목을 추가 하거나 제거할 때 알림을 제공 하는 컬렉션 클래스

        public ObservableCollection<Emp> Emps { getset; }


        public MainWindowViewModel()

        {

            Emps = new ObservableCollection<Emp>();

            Emps.Add(new Emp { Ename = "홍길동", Job = "Salesman" });

            Emps.Add(new Emp { Ename = "김길동", Job = "Clerk" });

            Emps.Add(new Emp { Ename = "정길동", Job = "Manager" });

            Emps.Add(new Emp { Ename = "박길동", Job = "Salesman" });

            Emps.Add(new Emp { Ename = "성길동", Job = "Clerk" });

            AddEmpCommand = new RelayCommand(AddEmp);

        }


        public void AddEmp(object param)

        {

            Emps.Add(new Emp { Ename = param.ToString(),Job="New Job"});

        }

    }

}


  • Client : [MainWindow.xaml], 여기서 Button은 Command Invoker


<Window x:Class="CommandExam.MainWindow"

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

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

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:CommandExam"

        mc:Ignorable="d"

        Title="MainWindow" SizeToContent="Width">

    <Window.DataContext>

        <local:MainWindowViewModel/>

    </Window.DataContext>

    <StackPanel>

        <TextBlock>사원 이름을 입력하세요.</TextBlock>

        <TextBox x:Name="txtName"  Text=”{Binding SelectedEmp.Ename}”/>

        <Button Command="{Binding AddEmpCommand}" CommandParameter="{Binding Text, ElementName=txtName}">Add</Button>

        <ListBox ItemsSource="{Binding Emps}" 

                 SelectedItem="{Binding SelectedEmp}"

                 DisplayMemberPath="Ename"

                 x:Name="empListBox"/>

        <Label x:Name="label" Content="{Binding SelectedItem, ElementName=empListBox}" 

               HorizontalAlignment="Center" 

               Height="40" 

               Margin="10,0,0,0" Width="137"/>    

</StackPanel>

</Window>


  • 위 예제에서 Command Invoker는 MainWindow.xaml의 버튼 이며  Command Target(Receiver)은 MainWindowViewModel, ConcreteCommand Object는 RelayCommand 객체이다.


#MVVM#COMMAND패턴#WPFMVVM#MVVM이란#WPF강좌#WPF교육#WPF동영상#WPF학원

MVVM, Command패턴, WPFMVVM, MVVM이란, WPF강좌, WPF교육, WPF동영상, WPF학원

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...