관리 메뉴

KorSA

WPF 코드 상에서 Event, Command 발생시키기 본문

Development Experience/C#

WPF 코드 상에서 Event, Command 발생시키기

Praiv. 2020. 3. 4. 17:45
320x100

WPF의 MVVM 모델에선

View에서 UIElement를 만들고 ViewModel의 Property들과 Binding을 한다.

 

특정 행동을 취하고 싶을 땐 Command 객체를 ViewModel에서 생성하고,

이 Command를 View에 바인딩시킬 수 있다.

 

ViewModel에서 View에게 어떤 행동을 시키고자 할 때

나는 Action 객체를 ViewModel에서 만들고

View의 특정 행동과 이 Action 객체를 바인딩시켜준다.

(ViewModel에서 Action을 통해 View를 건드리는 게 옳은 방법인지 모르겠으나,

 초보 개발자인 나는 일단 이런 식으로 구현한다..)

 

 

보통의 경우 위와 같이 Binding을 통해 View-ViewModel 간의 데이터 통신을 해결하였다.

 

오늘 업무 중 위와 같은 방식으로 해결이 잘 안되는 이슈가 있었다.

 

사용자가 View의 Textbox에서 Text를 입력하고 엔터를 클릭했을 때

특정 버튼을 클릭한 것과 동일한 효과를 내고 싶었는데, 이게 생각보다 쉽지 않았다.

좀 더 정확히 말하자면, 특정 버튼에 바인딩된 Command를 실행시키고 싶었다.

여기선 ApplyCommand라고 하자.

 

처음엔 Textbox에 KeyBinding을 넣어보았다.

 

<TextBox>

  <TextBox.InpuBindings>

    <KeyBinding Command="{Binding ApplyCommand}" Key="Enter"/>

    <KeyBinding Command="{Binding ApplyCommand}" Key="Return"/>

 </TextBox.InpuBindings>

</TextBox>

 

 

이런 식으로.

 

Command는 잘 수행되었다.

하지만 문제가 있었으니, 그건 바로 Textbox의 Text가 ViewModel에 반영이 안된다는 것이었다.

ApplyCommand는 Textbox의 Text 를 이용하기 때문에

사용자가 입력한 최신 값을 사용해야 했다.

하지만 ViewModel의 Text는 예전 값 그대로였다.

TextBox는 Focus가 다른 UIElement로 옮겨가야 PropertyChange event를 발생시키는 것 같다.

 

무튼...

그래서 View의 Code Behind 에서 ViewModel의 Text를 TextBox의 Text로 바꾼다음 Click 이벤트를 발생시키기로 하였다.

 

this.myButton.RaiseEvent(new RoutedEvnetArgs(ButtonBase.ClickEvent));

 

이런 식으로.

 

ViewModel의 Text 값은 최신 값으로 잘 바뀌었고 Click Event도 잘 수행되었다.

하지만 또 문제가 있었으니, Click 이벤트만 발생하고 Command가 호출되질 않았던 것이다.

내가 원하는 건 버튼에 할당된 Command를 수행하는 것이었기에 이 방법도 포기했다.

 

마지막으로 View의 Code Behind 에서 RaiseEvent() 대신 Command.Execute() 를 수행하기로 했다.

 

this.myButton.Command.Execute(this.myButton.CommandParameter);

 

이런 식으로.

 

드디어..!!

수행되었다. Command가.

 

PS ) View의 Code Behind를 사용하는 건 안좋은 습관이라고 하던데, 이럴 땐 Code Behind 없이 구현할 다른 방법이 있을까? 좀 더 나아가서 View가 동적으로 여러 동작을 하게 되면 Code Behind의 사용 없이 동적인 모든 장면들을 구현할 수 있을까?

728x90
728x90
Comments