MVVM을 사용하여 WPF에서 새 창을 생성하는 최상의 방법
이웃 게시물:View Model이 양식을 닫는 방법을 선택합니다.MVVM 사용으로 창을 닫는 방법에 대한 비전을 게시했습니다.이제 질문이 있습니다. 어떻게 그것들을 열 수 있을까요.
메인 창(메인 뷰)이 있습니다.사용자가 "Show" 버튼을 클릭하면 "Demo" 창(모달 대화 상자)이 표시됩니다.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
}
}
- "표시" 버튼 상태를 변경해야 하는 경우(활성화/비활성화) 버튼 상태를 관리하는 로직을 추가해야 합니다.
- 소스 코드는 "구형" WinForms 및 MFC 소스와 매우 유사합니다. 이것이 좋은 것인지 나쁜 것인지 잘 모르겠습니다. 조언 부탁드립니다.
- 제가 놓친 또 다른 것이 있나요?
또 다른 접근 방식:
MainWindowView Model에서는 명령의 IC 명령 인터페이스를 반환하는 "ShowCommand" 속성을 구현합니다.명령 차례:
- "ShowDialogEvent"를 발생시킵니다.
- 버튼 상태를 관리합니다.
이 접근 방식은 MVVM에 더 적합하지만 추가 코딩이 필요합니다.ViewModel 클래스는 "대화 상자 표시"를 할 수 없으므로 MainWindowViewModel은 "ShowDialogEvent", 즉 MainWindow_Loaded 메서드에 이벤트 핸들러를 추가해야 하는 MainWindowView만 발생시킵니다. 이는 다음과 같습니다.
((MainWindowViewModel)DataContext).ShowDialogEvent += ShowDialog;
(ShowDialog - '수정'과 유사함)Button_Click' 메서드입니다.)
그래서 제 질문은: 1입니다.다른 접근법이 있습니까? 2. 목록 중 하나가 좋거나 나쁘다고 생각하십니까?(왜?)
다른 어떤 생각이든 환영합니다.
감사해요.
일부 MVVM 프레임워크(예: MVVM Light)는 중재자 패턴을 사용합니다.따라서 새 창을 열기 위해(또는 보기를 만들기 위해) 일부 보기 관련 코드가 중재자의 메시지를 구독하고 보기 모델이 이러한 메시지를 보냅니다.
다음과 같이:
서브스크립션
Messenger.Default.Register<DialogMessage>(this, ProcessDialogMessage);
...
private void ProcessDialogMessage(DialogMessage message)
{
// Instantiate new view depending on the message details
}
뷰 모델에서
Messenger.Default.Send(new DialogMessage(...));
저는 애플리케이션의 UI 부분이 지속되는 한 "지속되는" 싱글톤 클래스에서 구독을 하는 것을 선호합니다.요약: ViewModel은 "I need to create view(보기를 만들어야 합니다)"와 같은 메시지를 전달하고 UI는 이러한 메시지를 수신하여 해당 메시지에 대해 작업을 수행합니다.
물론 "이상적인" 접근법은 없습니다.
저도 최근에 이 문제에 대해 생각하고 있었습니다.프로젝트에서 유니티를 '컨테이너'로 사용하거나 의존성 주입을 위해 사용할 수 있는 아이디어가 있습니다.내 생각엔 보통은 당신이 다른 사람들보다App.OnStartup()
모델, 뷰 모델 및 뷰를 작성하고 각 모델에 적합한 참조를 제공합니다.Unity를 사용하여 컨테이너에 모델에 대한 참조를 제공한 다음 컨테이너를 사용하여 뷰를 '해결'합니다.Unity 컨테이너는 뷰 모델을 주입하므로 직접 인스턴스화하지 않습니다.당신의 견해가 해결되면, 당신은 전화를 합니다.Show()
그 위에
예를 들어 본 비디오에서 Unity 컨테이너가 로컬 변수로 생성되었습니다.OnStartup
앱 클래스에서 이 속성을 공용 정적 읽기 전용 속성으로 만든 경우에는 어떻게 됩니까?그런 다음 기본 보기 모델에서 이 창을 사용하여 새 보기에 필요한 리소스를 자동으로 주입하여 새 창을 만들 수 있습니다. 같은 거.App.Container.Resolve<MyChildView>().ShowDialog();
.
테스트에서 유니티 컨테이너에 대한 호출 결과를 조롱할 수 있다고 생각합니다.은 또다음같방쓸수있다습니을법은과와 같은 을 쓸 .ShowMyChildView()
앱 클래스에서, 기본적으로 위에서 설명한 대로 합니다.로의 전화를 조롱하는 것은 쉬울지도 모릅니다.App.ShowMyChildView()
그것은 단지 a를 반환할 것이기 때문에.bool?
친구?
음, 그것은 그냥 사용하는 것보다 더 좋지 않을 수도 있습니다.new MyChildView()
하지만 그건 제가 생각한 작은 아이디어입니다.나눠먹어야겠다고 생각했어요.=)
제가 조금 늦었지만, 기존 답변으로는 부족하다고 생각합니다.그 이유를 설명하겠습니다.일반적으로:
- View에서 View Model에 액세스해도 됩니다.
- ViewModel에서 View에 액세스하는 것은 잘못된 것입니다. 순환 종속성이 발생하고 ViewModel을 테스트하기가 어렵기 때문입니다.
베니 조비건의 대답:
App.Container.Resolve<MyChildView>().ShowDialog();
이것은 실제로 아무것도 해결하지 못합니다.View Model에서 View에 엄격하게 결합된 방식으로 액세스하고 있습니다.와의 유일한 차이점은new MyChildView().ShowDialog()
당신이 간접적인 층을 통과했다는 것입니다.내 자식 뷰어에 직접 전화하는 것보다 더 좋은 점은 없습니다.
보기에 인터페이스를 사용하는 것이 더 깨끗합니다.
App.Container.Resolve<IMyChildView>().ShowDialog();`
이제 뷰 모델이 뷰에 단단히 결합되지 않습니다.그러나 각 뷰에 대한 인터페이스를 만드는 것은 매우 비현실적입니다.
아르코넛의 대답:
Messenger.Default.Send(new DialogMessage(...));
더 낫습니다.Messenger 또는 Event Aggregator 또는 다른 pub/sub 패턴은 MVVM의 모든 것에 대한 보편적인 솔루션인 것 같습니다 :) 단점은 디버깅하거나 탐색하기가 더 어렵다는 것입니다.DialogMessageHandler
너무 간접적인 거예요.예를 들어 DialogMessage를 수정하여 Dialog의 출력을 읽는 방법은 무엇입니까?
내 솔루션:
다음과 같이 MainWindowViewModel에서 창을 열 수 있습니다.
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는 대화 상자의 보기 모델만 사용하므로 보기 모델은 보기와 완전히 독립적입니다.런타임에 DialogService는 적절한 보기(예: 명명 규칙 사용)를 찾아 표시하거나 단위 테스트에서 쉽게 조롱할 수 있습니다.
제 경우 다음 인터페이스를 사용합니다.
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;}
}
여기서 DialogButton은 DialogResult 또는 I 명령 또는 둘 다를 지정합니다.
Silverlight에서 Modal Dialogs를 표시하기 위한 현재 MVVM 솔루션을 살펴보십시오.당신이 언급한 대부분의 문제를 해결하지만 플랫폼별로 완전히 추상화되어 재사용할 수 있습니다.또한 저는 IC 명령을 구현하는 Delegate Commands와의 코드 뒤에만 바인딩을 사용하지 않았습니다.Dialog는 기본적으로 View(보기) - 자체 View Model(보기 모델)이 있으며 기본 화면의 View Model(보기 모델)에서 표시되지만 Deagate Command 바인딩을 통해 UI에서 트리거되는 별도의 컨트롤입니다.
MVVM 및 Silverlight 4를 지원하는 Modal 대화 상자에서 Silverlight 4 솔루션 전체 보기
저는 뷰 간에 전달되는 모든 정보를 처리하는 컨트롤러를 사용합니다.모든 뷰 모델은 컨트롤러의 메소드를 사용하여 대화상자, 다른 뷰 등으로 구현할 수 있는 추가 정보를 요청합니다.
다음과 같습니다.
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();
...
}
}
나의 접근법은 아드리안과 비슷합니다.그러나 저의 경우 컨트롤러는 구체적인 보기 유형에서 작동하지 않습니다.컨트롤러는 View 모델과 동일한 방식으로 View와 완전히 분리됩니다.
WPF(WPF Application Framework)의 View Model 예제에서 이 기능을 확인할 수 있습니다.
.
안부 전합니다,
제이비
언급URL : https://stackoverflow.com/questions/2108949/the-best-approach-to-create-new-window-in-wpf-using-mvvm
'programing' 카테고리의 다른 글
WPF 문자열 형식={0:C} 달러로 표시 (0) | 2023.05.07 |
---|---|
Linux: 대상 dir(존재하지 않는 경우) 복사 (0) | 2023.05.07 |
SQL Server의 행 간격띄우기 (0) | 2023.05.07 |
Windows의 Git 심볼릭 링크 (0) | 2023.05.07 |
sed를 사용하여 문자열에서 첫 번째 X 문자를 제거하려면 어떻게 해야 합니까? (0) | 2023.05.07 |