MVVM을 사용하여 WPF에서 새 창을 만드는 가장 좋은 방법
이웃 게시물에서 : ViewModel이 양식을 어떻게 닫아야합니까? MVVM 사용으로 창을 닫는 방법에 대한 비전을 게시했습니다. 이제 질문이 있습니다. 어떻게 열 수 있습니까?
기본 창 (기본보기)이 있습니다. 사용자가 "표시"버튼을 클릭하면 "데모"창 (모달 대화 상자)이 표시됩니다. MVVM 패턴을 사용하여 창을 만들고 여는 바람직한 방법은 무엇입니까? 두 가지 일반적인 접근 방식이 있습니다.
첫 번째 (아마 가장 간단한 것). 이벤트 처리기 "ShowButton_Click"은 다음과 같은 방식으로 기본 창 뒤에있는 코드에서 구현되어야합니다.
private void ModifyButton_Click(object sender, RoutedEventArgs e)
{
ShowWindow wnd = new ShowWindow(anyKindOfData);
bool? res = wnd.ShowDialog();
if (res != null && res.Value)
{
// ... store changes if neecssary
}
}
- "Show"버튼 상태를 변경 (활성화 / 비활성화)해야하는 경우 버튼 상태를 관리하는 로직을 추가해야합니다.
- 소스 코드는 "구식"WinForms 및 MFC 소스와 매우 유사합니다. 이것이 좋은지 나쁜지 확실하지 않습니다.
- 내가 놓친 다른 것이 있습니까?
또 다른 접근 방식 :
MainWindowViewModel에서 명령의 ICommand 인터페이스를 반환하는 "ShowCommand"속성을 구현합니다. 차례로 Comman :
- "ShowDialogEvent"가 발생합니다.
- 버튼 상태를 관리합니다.
이 접근 방식은 MVVM에 더 적합하지만 추가 코딩이 필요합니다. ViewModel 클래스는 "대화 상자를 표시"할 수 없으므로 MainWindowViewModel은 "ShowDialogEvent"만 발생시킵니다. MainWindowView는 MainWindow_Loaded 메서드에 이벤트 처리기를 추가해야합니다. :
((MainWindowViewModel)DataContext).ShowDialogEvent += ShowDialog;
(ShowDialog- 'ModifyButton_Click'메소드와 유사합니다.)
제 질문은 다음과 같습니다. 1. 다른 접근 방식이 있습니까? 2. 나열된 것 중 하나가 좋거나 나쁘다고 생각하십니까? (왜?)
다른 생각은 환영합니다.
감사.
저도 최근에이 문제에 대해 생각하고있었습니다. 프로젝트에서 Unity 를 '컨테이너'로 사용하거나 의존성 주입을 위해 사용하는 아이디어가 있습니다 . 일반적으로 App.OnStartup()
모델을 재정의 하고 만들고, 모델을보고, 거기에서보고, 각각에 적절한 참조를 제공하는 것 같습니다. Unity를 사용하여 컨테이너에 모델에 대한 참조를 제공 한 다음 컨테이너를 사용하여 뷰를 '해결'합니다. Unity 컨테이너는 뷰 모델을 삽입하므로 직접 인스턴스화 할 수 없습니다. 일단 당신의 견해가 해결되면 당신은 Show()
그것을 부릅니다 .
내가 본 예제 비디오에서 Unity 컨테이너는 OnStartup
. App 클래스에서 공용 정적 읽기 전용 속성으로 만든 경우 어떻게됩니까? 그런 다음 기본보기 모델에서이를 사용하여 새 창을 만들고 새보기에 필요한 리소스를 자동으로 주입 할 수 있습니다. 같은 것 App.Container.Resolve<MyChildView>().ShowDialog();
.
테스트에서 Unity 컨테이너에 대한 호출 결과를 어떻게 든 조롱 할 수 있다고 생각합니다. 또는 ShowMyChildView()
기본적으로 위에서 설명한대로 수행하는 App 클래스 와 같은 메서드를 작성할 수 있습니다. , eh?를 App.ShowMyChildView()
반환 하기 때문에 호출을 조롱하는 것이 쉬울 수 있습니다 bool?
.
글쎄, 그게을 사용하는 것보다 낫지는 않을 수도 new MyChildView()
있지만 내가 가진 작은 아이디어입니다. 나는 그것을 공유 할 것이라고 생각했다. =)
일부 MVVM 프레임 워크 (예 : MVVM Light )는 중재자 패턴을 사용 합니다. 따라서 새 창을 열거 나 뷰를 생성하기 위해 일부 뷰 특정 코드가 중개자의 메시지를 구독하고 ViewModel이 해당 메시지를 보냅니다.
이렇게 :
구독
Messenger.Default.Register<DialogMessage>(this, ProcessDialogMessage);
...
private void ProcessDialogMessage(DialogMessage message)
{
// Instantiate new view depending on the message details
}
ViewModel에서
Messenger.Default.Send(new DialogMessage(...));
나는 애플리케이션의 UI 부분이하는 한 "존재하는"싱글 톤 클래스에서 구독을하는 것을 선호한다. 요약하자면 ViewModel은 "I need to create a view"와 같은 메시지를 전달하고 UI는 해당 메시지를 수신하고 이에 대해 조치를 취합니다.
확실히 "이상적인"접근 방식은 없습니다.
조금 늦었지만 기존 답변이 충분하지 않습니다. 이유를 설명하겠습니다. 일반적으로 :
- View에서 ViewModel에 액세스하는 것은 괜찮습니다.
- ViewModels에서 뷰에 액세스하는 것은 잘못된 것입니다. 순환 종속성을 도입하고 ViewModels를 테스트하기 어렵게 만들기 때문입니다.
Benny Jobigan의 답변 :
App.Container.Resolve<MyChildView>().ShowDialog();
이것은 실제로 아무것도 해결하지 않습니다. ViewModel에서 뷰에 연결되는 방식으로 액세스하고 있습니다. 와의 유일한 차이점 new MyChildView().ShowDialog()
은 간접적 인 레이어를 통과했다는 것입니다. MyChildView ctor를 직접 호출하는 것보다 이점이 없습니다.
보기에 인터페이스를 사용하면 더 깨끗해질 것입니다.
App.Container.Resolve<IMyChildView>().ShowDialog();`
이제 ViewModel은 뷰에 타이트하게 결합되지 않습니다. 그러나 각 뷰에 대한 인터페이스를 만드는 것은 매우 비현실적입니다.
arconaut 's anwer :
Messenger.Default.Send(new DialogMessage(...));
it's better. It seems like Messenger or EventAggregator or another pub/sub patterns are universal solution for everyhing in MVVM :) The disadvantage is that it's harder to debug or to navigate to DialogMessageHandler
. It's too indirect imho. For example, how would you read output form the Dialog? by modifying DialogMessage?
My Solution:
you can open window from MainWindowViewModel like this:
var childWindowViewModel = new MyChildWindowViewModel(); //you can set parameters here if necessary
var dialogResult = DialogService.ShowModal(childWindowViewModel);
if (dialogResult == true) {
//you can read user input from childWindowViewModel
}
DialogService takes just dialog's ViewModel, so your viewmodels are totally independent from Views. At runtime, DialogService can find appropriate view (using naming convention for example) and shows it, or it can be easily mocked in unit tests.
in my case I use this interfaces:
interface IDialogService
{
void Show(IDialogViewModel dialog);
void Close(IDialogViewModel dialog);
bool? ShowModal(IDialogViewModel dialog);
MessageBoxResult ShowMessageBox(string message, string caption = null, MessageBoxImage icon = MessageBoxImage.No...);
}
interface IDialogViewModel
{
string Caption {get;}
IEnumerable<DialogButton> Buttons {get;}
}
where DialogButton specifies DialogResult or ICommand or both.
Take a look at my current MVVM solution for showing Modal Dialogs in Silverlight. It solves most of the issues you mentioned yet its completely abstracted from platform specific things and can be reused. Also i used no code-behind only binding with DelegateCommands that implement ICommand. Dialog is basically a View - a separate control that has its own ViewModel and it is shown from the ViewModel of the main screen but triggered from the UI via DelagateCommand binding.
See full Silverlight 4 solution here Modal dialogs with MVVM and Silverlight 4
I use a controller which handles all information passing between views. All viewmodels use methods in the controller to request more information which can be implemented as dialogs, other views etc.
It looks something like this:
class MainViewModel {
public MainViewModel(IView view, IModel model, IController controller) {
mModel = model;
mController = controller;
mView = view;
view.DataContext = this;
}
public ICommand ShowCommand = new DelegateCommand(o=> {
mResult = controller.GetSomeData(mSomeData);
});
}
class Controller : IController {
public void OpenMainView() {
IView view = new MainView();
new MainViewModel(view, somemodel, this);
}
public int GetSomeData(object anyKindOfData) {
ShowWindow wnd = new ShowWindow(anyKindOfData);
bool? res = wnd.ShowDialog();
...
}
}
내 접근 방식은 adrianm과 비슷합니다. 그러나 제 경우에는 Controller가 구체적인 View 유형으로 작동하지 않습니다. Controller는 ViewModel과 같은 방식으로 View에서 완전히 분리됩니다.
이것이 어떻게 작동하는지는 WPF 애플리케이션 프레임 워크 (WAF) 의 ViewModel 예제에서 볼 수 있습니다 .
.
친애하는,
jbe
참조 URL : https://stackoverflow.com/questions/2108949/the-best-approach-to-create-new-window-in-wpf-using-mvvm
'development' 카테고리의 다른 글
문자열의 시작이 in보다 느린 이유는 무엇입니까? (0) | 2021.01.08 |
---|---|
Objective-C의 속성 및 인스턴스 변수 (0) | 2021.01.08 |
Windows에서 Eclipse를 어떤 폴더에 설치해야합니까? (0) | 2021.01.08 |
AngularJS와 함께 백본 모델 사용 (0) | 2021.01.08 |
"다운 캐스팅"unique_ptr (0) | 2021.01.08 |