WPF Socket통신과 InotifypropertyChanged

안녕하세요 Socket통신과 InotifypropertyChanged 속성에 대해서 공부하고 있습니다.
Socket 통신에대해 아직 공부중이고 실력이 많이 부족하지만 여기저기 자료를 찾아보면서 스스로 공부중에 있습니다.
공부하던 중 InotifypropertyChanged속성에 대해 알게 되었고 이 속성이 어떠한 역할을하는지는 자세히는 모르지만
속성이 변경되면 다른 항목이 자동으로 업데이트를 해주는 기능으로만 알고 있습니다.

구현하고 싶은 내용
Send라는 버튼의 이벤트 동작이 발생했을 때 전에 입력된 내용들과 같이 보내지도록 하는 겁니다.
현재 Send버튼을 누르면 전에 입력된 내용이 그대로 남아있습니다.

  • (엔터키를 입력했을때 메시지가 전송되는 이벤트의 속성도 존재하나요?)

알고싶은 것
INotifyPropertyChanged 속성에 대해 좀 자세히 알고 싶습니다.
검색해서 찾아보았지만 잘 이해가 되지 않아 질의 드립니다. 위의 프로젝트에서 발생하는 INotifyPropertyChanged
동작방식?( )
속성에 대해서 설명해주시면 너무나 감사드리겠습니다.

작성한 프로젝트의 zip파일입니다.

3개의 좋아요

원하시는 부분이 Send 버튼을 눌렀을 때, Send 버튼 좌측에 위치한 메시지를 입력하는 텍스트 박스를 비우고자 하시는 게 맞나요?

맞다는 가정 하에 아래 내용을 적습니다.


INotifyPropertyChanged는 무엇인가?
INotifyPropertyChanged는 이름 그대로 속성이 변경되었음을 알리는 기능을 구현합니다. INotifyPropertyChanged 인터페이스를 구현하는 객체는 속성 값이 변경될 때 발생하는 PropertyChanged라는 이벤트를 가지며, 외부에서 이 이벤트를 구독해 속성 값이 변경될 때마다 알림을 받을 수 있습니다.

WPF의 데이터 바인딩에서 INotifyPropertyChanged의 역할
WPF에서는 데이터 바인딩 시, PropertyChanged 이벤트를 가져와 구독하는 작업이 수행됩니다. 즉 PropertyChanged가 발생할 때 EventArgs로 변경된 속성의 이름을 받고, 변경된 속성의 값을 가져와 해당 속성과 바인딩된 DependencyProperty에 반영하는 것입니다.

  • 참고: INotifyPropertyChanged 인터페이스를 구현하지 않더라도 데이터 바인딩 자체는 작동합니다. 다만 강한 참조로 동작하므로 속성 값이 변경되더라도 업데이트에 문제가 있고, 이전 게시물에서 언급한 것처럼 메모리 누수 문제가 있습니다.

샘플 코드에서 메시지 박스가 업데이트되는 과정
작성자님께서 올리신 소스에서 메시지 박스(TextBox의 Text 속성)에 바인딩된 속성은 msg(msg1)이므로, TextBox의 Text 속성의 값은 msg 속성의 값을, msg 속성은 필드 변수 _txtInput의 값을 따라가며, msg 속성이 변경되었다는 PropertyChanged 이벤트가 발생할 때마다 업데이트가 발생합니다. 즉 아래와 같은 절차로 동작합니다.

  1. _txtInput 값 변경
  2. 업데이트를 원하는 시점(BtnSendAll_Clilck)에 PropertyChanged 이벤트를 발생시킴(변경 속성 이름: msg)
  3. msg의 Binding Target(TextBox.Text)에서 msg의 값을 확인하기 위해 msg의 getter 호출
  4. getter에서 _txtInput 값 반환
  5. Binding Target(TextBox.Text)에서 _txtInput 값을 반영

일반적으로는, 첨부하신 샘플 코드처럼 필드(_txtInput)의 값을 변경하고 해당 필드를 참조하는 속성(msg)에 대한 PropertyChanged 이벤트를 발생하는 메소드(NotifyPropertyChanged(“msg1”))를 호출하는 번거로운 방법보다는, 필드는 단지 속성의 getter setter 구현을 위한 장치 정도로만 이용하고 속성의 setter에서 값 변경과 PropertyChanged 이벤트 발생 메소드를 순차적으로 호출함으로써 이벤트를 발생시키는 방법을 즐겨 사용합니다. 절차는 다음과 같습니다.

  1. msg 속성에 값 할당(msg = string.Empty 등)
  2. msg setter 호출
  3. _txtInput 값 변경
  4. msg에 대한 PropertyChanged 이벤트 발생
  5. msg의 Binding Target(TextBox.Text)에서 msg의 값을 확인하기 위해 msg의 getter 호출
  6. getter에서 _txtInput 값 반환
  7. Binding Target(TextBox.Text)에서 _txtInput 값을 반영

처음에 업데이트가 안 된 이유

  1. Binding Source인 msg 속성의 값이 변경되지 않아서
  2. msg 속성에 대한 PropertyChanged 이벤트가 호출되지 않아서

msg의 값이 null인지, empty인지 확인하는 과정은 그다지 중요하지 않습니다. msg 속성의 값이 변경되어야(정확히는 setter가 호출되어야) PropertyChanged 이벤트가 발생하고, 바인딩된 TextBox에서 속성 값 변경을 감지해 변경 부분을 업데이트 할 텐데, setter가 호출되지 않으니 업데이트 역시 되지 않는 거죠. 두 번째 코드에서는 BtnSendAll_Clilck 메소드에서 msg1 = string.Empty ← 요 라인을 통해 msg1의 setter가 호출되어 속성 값(정확히는 getter에서 참조하는 _txtInput 필드의 값)도 변경되고, PropertyChanged 이벤트를 호출함으로써 속성 값 변경도 알리니까 원하시는 부분이 구현된 것이구요.

결론

  1. 첫 번째 샘플코드에서 메시지 박스가 비워지지 않은 것은 메시지 박스에 바인딩된 msg 속성 값이 변경되지도 않았고, msg 속성이 변경되었음을 알리는 PropertyChanged 이벤트가 발생하지도 않아서 그렇다.
  2. 두 번째 샘플코드에서는 BtnSendAll_Clilck 메소드 내에서 msg1 속성에 값을 할당하기도 했고, 할당 과정에서 PropertyChanged 이벤트가 발생하기도 해서 View에 반영된 것이다.
  3. 데이터 바인딩 시에는 속성 값이 변경되었는지를 알리는 기능을 구현해야 하고, 그 방법은 가급적(메모리 누수를 감안하면 사실상 반강제로) INotifyPropertyChanged 인터페이스를 구현함으로써 달성해야 한다.
  • 엔터 키 입력 시 전송 관련 부분은 wpf keydown event 등의 키워드로 검색해 보시면 금방 나올 것 같네요. 엄격한 MVVM 패턴 적용이 아니라면 코드 비하인드를 적절히 이용하는 선에서 어렵지 않게 구현 가능할 것으로 보입니다.
7개의 좋아요

자세한 설명과 친절하게 답변주셔서 정말 감사드립니다.
답변주신 내용을 토대로 공부하면서 하나씩 배워가도록 하겠습니다!
감사합니다~

2개의 좋아요