본문 바로가기
Programming/WPF

WPF. EventHandler를 비하인드 코드가 아닌 ViewModel에 구현하기

by 곰네Zip 2022. 10. 20.

WPF를 가지고 여러가지 만들다보면.. Event Handling을 처리해야할 경우가 제법 있다.

근데.. xaml에서 Event="MyEventHandlerName"을 입력하면.. 비하인드 코드에 작성이 된다.

뭐.. 비하인드 코드에 작성하는것이 잘못된건 아닌데.. MVVM패턴을 쓸때에는 가급적이면.. ViewModel에서 핸들링 하게 구현하는것이 더 좋다.

비하인드에 구현할 경우 여러가지 불필요한 코드들이 추가되어야하는 경우가 제법 있다. 그런 불필요한 코드들을 추가하기 싫다면.. VM을 static 또는 global로 선언하고, 그 안에서 모든 멤버들을 public으로 오픈하면 되는데..

ViewModel이 아닌 객체가 ViewModel의 멤버에 함부로 접근하도록 설계하는 것이 좋을지 나쁠지는 뭐... 

 비하인드 코드에 작성하려고한다면 다음과 같이 구현하면 될것이다.

//myView.xaml
<Button Click="Button1_Click" />

//myView.xaml.cs
private void Button1_Click(object sender, MouseEventArgs e){
}

 MouseEventArgs가 맞던가.. 

 뭐.. 여튼... 여기서 ViewModel에 접근하려면 다른 무언가를 통해 접근해주어야한다. 그게 싫다면 Event Handler를 ViewModel에 구현해주면 된다. 

//myView.xaml
<DataGrid>
   <i:Interaction.Triggers>
   		<i:EventTrigger EventName="MouseClick">
        	<i:InvoceCommandAction Command="{Binding Path=DataGridClickCommand}"
            					PassEventArgsToCommand="True" />          
        </i:EventTrigger>
   </i:Interaction.Triggers>
</DataGrid>

//myViewModel.cs
private DelegateCommand<MouseEventArgs> dataGridClickCommand;
public DelegateCommand<MouseEventArgs> DataGridClickCommand{
	get{
    	if( this.dataGridClickCommand == null){
        	this.dataGridClickCommand = 
            	new DelegateCommand<MouseEventArgs>(this.dataGridClickCommandExecute);
        }
        return this.dataGridClickCommand;
    }
}

private void dataGridClickCommandExecute(MouseEventArgs args){
}

 위와 같이 command로 처리 가능하다. i는 interactitivy namespace를 정의한것이고. (보통 포함되어있음)

 PassEventArgsToCommand를 True로 설정하면 각 event에 맞는 EventArgs가 Command로 전달된다. 만약 어느 event가 오는지 잘 모르겠으면.. ViewModel의 Command를 구현하는 부분에서, parameter를 object로 받아와서, 해당 object가 어느 형태인지 먼저 파악 후, 그에 맞게 Command Type을 변경해주면 된다.

 만약 EventArgs를 전달하지 않고, 다른 parameter를 전달하고자하면 PassEventArgsToCommand대신, CommandParameter를 이용하여 전달해주면 된다.

반응형

댓글