예전에는 WPF 개발을 MVVM 구조로 진행해서 ViewModel과 Model을 사용해서 데이터를 전달하곤 했는데, 이번에는 개발 디자인 패턴이 바뀌어서 MVC로 진행하게 되었습니다.
데이터 전달을 EventHandler라는 것을 사용하게 되는데 간단히 정리해보도록 하겠습니다.
1. EventHander 선언
public event EventHandler<string> TitleSelected;
// string 타입의 데이터를 이벤트 핸들러에 전달할 수 있음
2. EventHanlder가 사용될 이벤트 등록 및 구현
lv_Presents.SelectionChanged += Lv_Presents_SelectionChanged;
// ListView에서 항목이 변경될 때 실행되는 이벤트(Lv_Presents_SelectionChanged)를 등록
// 선택 항목이 바뀔 때마다 메서드가 호출
private void lv_Presents_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lv_Presents.SelectedItem is PresentModel model)
{
TitleSelected?.Invoke(this, model.title);
// this: 현재 UserControl을 이벤트 발신자로 지정
// model.title: 전달할 데이터
// ?.Invoke: 이벤트 구독자에게 데이터 전달(구독자가 없을 때 예외가 발생하지 않음)
}
}
3. 이벤트 구독 및 처리로직 구현
uc_Presents.TitleSelected += uc_Presents_TitleSelected;
// uc_Presents TitleSelected 이벤트가 발생하면, uc_Presents_TitleSelected 메서드 실행
// Window가 생성될 때 이벤트 핸들러를 등록하여 UserControl에서 발생한 이벤트를 받을 준비를 함
private void uc_Presents_TitleSelected(object sender, string title)
{
tblock_SelectedTitle.Text = title;
}
💡 이벤트 해제
* 객체가 더 이상 사용되지 않거나 이벤트를 더 이상 받을 필요가 없을 때는 -=로 해제하는 것이 좋음
* 이벤트 핸들러가 해제되지 않으면 구독자가 GC에 의해 수거되지 않기 때문에, 메모리 누수가 발생할 수 있음
새로운 Template을 만들어 사용할 경우, 내용(Content)을 표시하는 기능인 ContentPresenter도 함께 선언해야 합니다.
3. TemplateBinding
ControlTemplate 안에서 외부의 속성 값을 바인딩할 때 사용합니다.
여기서는 DefaultButton을 사용한 Button의 Background인 DodgerBlue를 참조하게 됩니다.
4. Trigger
마지막으로 trigger는 특정 조건이 만족될 때(여기서는 마우스가 버튼 위에 올라왔을 때) 스타일이나 속성을 변경합니다. 이를 통해 ControlTemplate에서 설정된 속성들을 변경할 수 있습니다.
1번 코드와 2번 코드는 Button 안의 TextBlock에 FontWeight를 직접 설정했느냐의 차이가 있습니다.
1번은
Complate.Trigger → Button 속성 변경 → ContentPresenter: 변경된 속성을 Button의 자식 요소인 TextBlock에 전달합니다.
2번은
Complate.Trigger→ Button 속성 변경→ ContentPresenter: 변경된 속성을 Button의 자식 요소인 TextBlock에 전달합니다. 하지만, 자식 요소에서 직접 설정된 속성은 ControlTemplate의 외부에서 설정된 것으로 간주되어, ControlTemplate의 트리거에서 영향을 받지 않습니다.
⭐ 간단하게 정리하면, ControlTemplate은 전체적인 Template를 control할 수 있지만, <> 안에서 직접 설정된 요소는 변경할 수 없습니다.