16. Command
01. Command 이론
01.1 ICommand 사용 방법
(1) ViewModel 에 ICommand 구현체를 만들고, 원하는 '메서드'를 등록합니다.
MyCommand cmd = new MyCommand(메서드);
(2) View에 ICommand 구현체인 cmd를 바인딩 합니다.
<Button Command="{Binding cmd}"/>
01.2 ICommand
- 목적: XAML 코드 비하인드가 아닌, 별도의 ViewModel 클래스에서 로직 함수를 구현합니다.
- 방법: ICommand 인터페이스의 Execute( ) 함수의 구현부에, 이벤트 핸들러 로직을 구현해 대신 사용할 수 있습니다.
01.3 ICommand
ICommand는 WPF 컨트롤의 Command 속성에 Binding 하기 위해 사용합니다.
위순서도는 ICommand의 동작방식입니다.
CanExecuteChanged이벤트가발생하면
CanExecute를통해 컨트롤이 사용가능한지 체크하고 IsEnable 속성을 업데이트합니다.
IsEnable이적용되는컨트롤은ButtonBase,MenuItem,Hyperlink등이있습니다.
사용자명령이 발생하면 IsEnable이 true로 활성화된 컨트롤은 Execute에 정의된 동작이 실행됩니다.
01.4 Command
UI 컨트롤의 Clicked나 Tapped와 같은 속성입니다.
UI 컨트롤의 Command 속성을 ViewModel 에서 로직과 DataBinding 하면, 대체할 수 있습니다.
이는 MVVM 패턴 구조를 단순하게 합니다.
Command 속성은 다음 UI 컨트롤에서 지원합니다.
- Button
- MenuItem
- ToolbarItem
- SearchBar
- TextCell
- ImageCell
- ListView
- TapGestureRecognizer
Command를 지원하기 위해 이 Class들에는 2개의 공용 Property가 정의되어 있습니다.
- Command: System.Windows.Input.Icommand Type을 가집니다.
- CommandParameter: object타입입니다.
01.5 구현 방법
UI 컨트롤의Command 속성을 DataBinding 하려면
ViewModel에는 최소 1개 이상의 Public ICommand Type의 Property를 가져야 합니다.
ICommand interface는 다음 2개의 method와 1개의 event멤버를 포함하는 간단한 인터페이스입니다.
public interface ICommand
{
event EventHandler? CanExecuteChanged; // Excute를 실행할 수 있는 상태 확인 이벤트
bool CanExecute(object? parameter); // Excute를 실행할 수 있는 상태 확인 조건
void Execute(object? parameter); // 실행(eg. 버튼 이벤트 핸들러)
}
02. 이벤트 핸들러 구현 예시
02.1
Title="ICommandTest" Height="80" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Text=""/>
<Button Grid.Column="1" Content="Button"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Click="Button_Click"
/>
</Grid>
02.2
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("MyICommand Execute()");
}
02.3
버튼을 누르면, 버튼 클릭 이벤트 > Button_Click 이벤트 핸들러 로직 > MessageBox 실행
02.4
02.5
간단한 버튼 클릭 이벤트 핸들러를 구현했습니다.
위에서 구현한 버튼 클릭 이벤트 핸들러를
MVVM의 ViewModel 클래스에서 Command 구현으로 대체합니다.
비교해봅시다.
03. Command 사용 준비
03.1위 이벤트 핸들러 구현 예제에서, 코드 비하인드에 구현한 "버튼 클릭 이벤트 핸들러" 부분을 제거합니다.
03.2 ViewModel 폴더와 ViewModel.cs 생성
03.3 ViewModel 클래스에 로직 구현
// View의 코드 비하인드에서
// 버튼 클릭 이벤트 핸들러에 작성한 로직을
// ViewModel에서 함수로 구현합니다.
public void DisplayMessage()
{
MessageBox.Show("Clicked");
}
03.3 View에 ViewModel 연동하기
xmlns:vm ="clr-namespace:ICommandTest.ViewModel"
<Window.DataContext>
<vm:MainViewModel />
</Window.DataContext>
View는 XAML과 CS로 이루어진 하나의 실행 단위입니다.
ViewModel은 비지니스 로직으로 View와 관련없는 별도의 CS 파일입니다.
그러므로 View는 ViewModel을 알 수 없습니다.
(1)View에서 ViewModel 클래스에 접근하고 객체 생성에 사용하려면,
(2)View에 ViewModel의 네임스페이스 xmlns 키워드를 사용해 추가해야 합니다.
(3)그리고, Window 의 DataContext에 ViewModel 네임스페이스의 ViewModel Class를 등록해야합니다.
*Context는 소프트웨어 개발에서는 호출, 응답을 위한 환경정보, 실행환경 이라는 의미입니다.
*DataContext에 알 수 없는 오류로 녹색 및 파란색, 줄이 그어진다면, 빌드 또는 Visual Studio를 재실행 해 주세요.
03.4 Command 속성 미리보기
버튼 클릭했을 때, ViewModel의 DisplayMessage 메서드를 실행하도록 바인딩 하는 것이 목표입니다.
ICommand 구현체를 이용해야 합니다.
04. ICommand 구현
04.1 목표
View의 Button 컨트롤의 Command 속성에
ViewModel의 DisplayMessage 함수를 등록하기 위해
ICommand 구현체를 사용합니다.
04.2 ICommand 사용 방법
(1) ViewModel 로직에 ICommand 구현체를 만들고, 원하는 메서드를 등록합니다.
MyCommand cmd = new MyCommand(메서드);
(2) View에 ICommand 구현체인 cmd를 바인딩 합니다.
<Button Command="{Binding cmd}"/>
04.3 ICommand 구현
(1) ViewModel 폴더 하위에 Commands 폴더를 생성합니다.
(2) MessageCommands.cs 클래스 파일을 생성합니다.
(3) ICommand 인터페이스를 상속받고, ctrl+. 단축키로 인터페이스 요소를 자동 생성합니다.
(4) CanExecute( ) 메서드의 반환값을 true로 지정합니다. (편의를 위해)
04.4 Action 대리자를 정의하고, 생성자의 매개변수로 전달되도록 구현합니다.
ViewModel의 DisplayMessage 메서드는 반환값이 없기 때문에 Action 대리자를 사용합니다.
private Action _execute;
public Command(Action ViewModel_Method)
{
_execute = ViewModel_Method;
}
04.5 Command의 Execute( ) 메서드 로직 구현
class Command : ICommand
{
private Action _execute;
public Command(Action ViewModel_Method)
{
_execute = ViewModel_Method;
}
public event EventHandler? CanExecuteChanged;
public bool CanExecute(object? parameter) //컨트롤 활성화 여부, true지정
{
return true;
}
public void Execute(object? parameter)
{
_execute.Invoke();
}
}
04.6 ViewModel에서 메서드를 Command 구현체에 등록
MessageCommand 클래스 프로퍼티를 설정하고
MainViewModel 생성자에, Command 클래스에 DisplayMessage( ) 메서드를 할당합니다.
*Command 객체의 Action 대리자에 DisplayMessage( ) 메서드를 연결하는 작업입니다.
04.7 View 컨트롤에 Command 바인딩
04.8 테스트
04.9 실행구조
View(XAML 컨트롤에 Command에ViewModel 함수바인딩) >> ViewModel 프로퍼티 실행
ViewModel의 프로퍼티는 ICommand 인터페이스가 구현된 클래스의 프로퍼티를 내포함
ICommand 인터페이스가 구현된 클래스는 UI컨트롤이 동작하면, Execute( ) 함수가 실행된다.
04.10 Test
데이터 바인딩을 이용해, DisplayMessage( )가 동작할 때
View의 TextBox와 Button 위에 출력되는 문자열을 동시에 다른 문자로 출력되게 만들기
04.11
05. CommandParameter 구현 예시
05.1 Command 실행시 매개변수 넘기기구현
05.2
05.3
05.4
05.5
05.6
06. CanExecute 구현 예제
06.1
ICommand 인터페이스 구현 메소드 중 하나인 CanExecute( )는 boolean 타입 값을 리턴한다.
이를 활용해, 컨트롤을 true일때 활성화되고 false일때 비활성화 할 수 있다.
이를 활용해, TextBox 입력전 버튼이 비활성화 상태로, 글자 입력 후 활성화 하도록 구현한다.
06.2