안녕하세요, WPF에 입문한 지 얼마 안되는 개발자입니다!
WPF MVVM 패턴을 이용해서 개발 중인데, MainWindow 내에 새로운 Window를 팝업하는 버튼이 있습니다.
새로운 Window를 팝업 시키고, 그 팝업된 윈도우와 데이터 바인딩된 뷰모델의 데이터를 MainWindow의 뷰모델에게 넘기고 싶은데, 어떠한 구조가 좋을지 모르겠습니다.
안녕하세요, WPF에 입문한 지 얼마 안되는 개발자입니다!
WPF MVVM 패턴을 이용해서 개발 중인데, MainWindow 내에 새로운 Window를 팝업하는 버튼이 있습니다.
새로운 Window를 팝업 시키고, 그 팝업된 윈도우와 데이터 바인딩된 뷰모델의 데이터를 MainWindow의 뷰모델에게 넘기고 싶은데, 어떠한 구조가 좋을지 모르겠습니다.
MVVM Toolkit을 사용하신다면 Messenger를 이용하는 방법이 있을 것 같네요.
답변 감사드립니다!
윈도우도 객체라서 다른 프레임워크나 도구가 필요 없습니다.
한 객체에게 데이터를 전달하는 방법은 public set 이 있는 속성을 설정하거나,
// MainWindow.xaml.cs
// Window2 Open 버튼 이벤트 핸들러.
Window2 window2 = new Window2();
window.RequestData = new RequestData
{
Prop1 = _viewModel.Prop1,
Prop2 = _vlewModel.Prop2,
// ...
}
window2.Show();
생성자를 통해 전달하면 되고,
// MainWindow.xaml.cs
private RequestData _request = new(); // 수시로 업데이트 됨.
// Window2 Open 버튼 이벤트 핸들러.
Window2 window2 = new(_request);
window2.Show();
거꾸로 받고 싶다면, public get 속성을 통해 받으면 됩니다.
그러나, 다른 윈도우가 닫히면 속성을 읽을 수 없으므로, 다른 윈도우가 살아 있을 때, 이벤트를 통해 실시간으로 받으면 됩니다.
// Window2.xaml.cs
// ...
public event EventHandler<ResponseData> ResponseDataChanged;
public Window2()
{
// ...
_viewModel.PropertyChanged += OnViewModelChanged;
}
private void OnViewModelChanged(object s, EventArgs e) =>
UpdateResponse(_viewModel);
private void UpdateResponse(Window2ViewModel viewModel)
{
ResponseData response = // _viewModel 로부터 ReponseData 생성.
ResponseDataChanged?.Invoke(response);
}
public void Dispose()
{
_viewModel.Propertychanged -= OnViewModelChanged;
}
// MainWindow.xaml.cs
// Window2 Open 버튼 이벤트 핸들러.
Window2 window2 = new(_request);
window2.ResponseDataChanged += OnResponseDataChanged;
window2.Show();
// ...
private void OnResponseDataChanged(ReponseData response)
{
_viewModel = // response로부터 viewModel 재설정. => 데이터 바인딩에 의해 뷰에 반영됨.
// ...
}
만약 Window2가 뷰모델을 공개 속성으로 선언한다면, 그 뷰모델의 PropertyChanged 이벤트를 바로 사용할 수도 있습니다.
// MainWindow.xaml.cs
// Window2 Open 버튼 이벤트 핸들러.
Window2 window2 = new(_request);
window2.ViewModel.PropertyChanged += OnWindow2ViewModelPropertyChanged;
}
private void OnWindow2ViewModelPropertyChanged(object s, EventArgs e) =>
{
if (s is Window2ViewModel window2ViewModel)
{
// window2ViewModel로, MainWindow 뷰모델을 업데이트.
}
}
메신저보단 IoC(의존성 주입)을 사용하는것을 강력하게 추천드립니다.
답변 감사드립니다!
App.cs에 ServiceCollection 등록하는 것 말씀이시죠?
혹시 왜 강력 추천하시는지 말씀해 주실 수 있으신가요?
Messenger를 권장하지 않는 이유는, 의존이 생기기 때문입니다. 특정 메시지 관리하는 서비스에 의존적이게 되죠. (해당 서비스의 요구에 맞춘 추가적인 구현이 필요하고요)
대부분의 경우, A뷰모델에서 B 뷰모델로 데이터를 전달하는게 필요한게 아닌,
사실 앱 전체에서 공유되는 어떤 데이터를 관리할 수 있는 서비스가 필요했을 거라고 추측됩니다.
IoC는 어떤 의존관계에 있는 서비스를 근본적인 방식으로 결합도를 낮추면서도, 관계를 파악하기 쉬운 설계원칙을 적용할 수 있도록 해줍니다(생성자 주입).
IoC컨테이너(Microsoft.Extensions.DependencyInjection)와 같이 활용하면 서비스의 수명주기 관리, 의존 서비스를 알아서(?) 주입해주니까 굉장히 편합니다.
혹시나 예제 필요하시면,
제가 올렸던 게시글 한번 참고하시면 될 거 같습니다.
답변 감사드립니다! IoC 활용해서 진행중입니다ㅎㅎ