[.net] MVVM을 사용하여 WPF에서 대화 상자 처리

WPF의 MVVM 패턴에서 대화 상자 처리는보다 복잡한 작업 중 하나입니다. 뷰 모델은 뷰에 대해 아무것도 모르므로 대화 대화가 흥미로울 수 있습니다. ICommand뷰가 호출 할 때 대화 상자가 나타날 수 있다는 것을 노출시킬 수 있습니다.

누구든지 대화 상자의 결과를 처리하는 좋은 방법을 알고 있습니까? 와 같은 Windows 대화 상자에 대해 말하고 MessageBox있습니다.

이 작업을 수행 한 방법 중 하나는 대화 상자가 필요할 때 뷰가 구독하는 뷰 모델의 이벤트가있었습니다.

public event EventHandler<MyDeleteArgs> RequiresDeleteDialog;

이것은 괜찮지 만 뷰에 멀리 떨어져있는 코드가 필요하다는 것을 의미합니다.



답변

1990 년대 모달 대화 상자를 포기하고 대신 VM의 부울에 연결된 가시성을 가진 오버레이 (캔버스 + 절대 위치 지정)로 컨트롤을 구현하는 것이 좋습니다. 아약스 타입 컨트롤에 더 가깝습니다.

이것은 매우 유용합니다 :

<BooleanToVisibilityConverter x:Key="booltoVis" />

에서와 같이 :

<my:ErrorControl Visibility="{Binding Path=ThereWasAnError, Mode=TwoWay, Converter={StaticResource booltoVis}, UpdateSourceTrigger=PropertyChanged}"/>

다음은 사용자 정의 컨트롤로 구현 한 방법입니다. ‘x’를 클릭하면 usercontrol의 코드 뒤에 코드 줄로 컨트롤이 닫힙니다. .exe에 뷰가 있고 dll에 ViewModels가 있으므로 UI를 조작하는 코드에 대해 나쁘지 않습니다.

Wpf 대화 상자


답변

이를 위해 중개자를 사용해야합니다. 중재자는 일부 구현에서 메신저 라고도하는 일반적인 디자인 패턴 입니다. 이는 Register / Notify 유형의 패러다임이며 ViewModel 및 Views가 낮은 결합 메시징 메카니즘을 통해 통신 할 수 있도록합니다.

Google WPF 제자 그룹을 확인하고 중재자를 검색해야합니다. 당신은 대답에 매우 만족할 것입니다 …

그러나 다음과 같이 시작할 수 있습니다.

http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/

즐겨 !

편집 : MVVM Light Toolkit 으로이 문제에 대한 답을 볼 수 있습니다.

http://mvvmlight.codeplex.com/Thread/View.aspx?ThreadId=209338


답변

좋은 MVVM 대화 상자는 다음과 같아야합니다.

  1. XAML로만 선언하십시오.
  2. 데이터 바인딩에서 모든 동작을 가져옵니다.

불행히도 WPF는 이러한 기능을 제공하지 않습니다. 대화 상자를 표시하려면에 대한 코드 숨김 호출이 필요합니다 ShowDialog(). 대화 상자를 지원하는 Window 클래스는 XAML에서 선언 할 수 없으므로에 데이터 바인딩하기가 쉽지 않습니다 DataContext.

이 문제를 해결하기 위해 논리 트리에 앉아 데이터 바인딩을 a로 릴레이 Window하고 대화 상자 표시 및 숨기기를 처리 하는 XAML 스텁 컨트롤을 작성했습니다 . 여기에서 찾을 수 있습니다 : http://www.codeproject.com/KB/WPF/XAMLDialog.aspx

실제로 사용하기 쉽고 ViewModel을 이상하게 변경하지 않아도되며 이벤트 나 메시지가 필요하지 않습니다. 기본 호출은 다음과 같습니다.

<dialog:Dialog Content="{Binding Path=DialogViewModel}" Showing="True" />

설정하는 스타일을 추가하고 싶을 것입니다 Showing. 내 기사에서 설명합니다. 이것이 도움이되기를 바랍니다.


답변

MVVM과의 대화 에이 방법을 사용 합니다 .

지금해야 할 일은 뷰 모델에서 다음을 호출하는 것입니다.

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);


답변

내 현재 솔루션은 언급 한 대부분의 문제를 해결하지만 플랫폼 관련 사항에서 완전히 추상화되어 재사용 할 수 있습니다. 또한 ICommand를 구현하는 DelegateCommands와의 바인딩 만 코드 숨김을 사용하지 않았습니다. Dialog는 기본적으로 View-자체 ViewModel을 가진 별도의 컨트롤이며 기본 화면의 ViewModel에서 표시되지만 DelagateCommand 바인딩을 통해 UI에서 트리거됩니다.

MVVM 및 Silverlight 4를 사용한 모달 대화 상자는 여기에서 전체 Silverlight 4 솔루션을 참조하십시오.


답변

나는 MVVM을 배울 때 (정지 학습) 잠시 동안이 개념으로 어려움을 겪었습니다. 내가 결정한 것과 다른 사람들이 이미 결정했지만 분명하지 않은 것은 다음과 같습니다.

내 원래 생각은 ViewModel이 대화 상자를 표시하는 방법을 결정하는 비즈니스가 없기 때문에 대화 상자를 직접 호출 할 수 없다는 것입니다. 이 때문에 나는 MVP에서와 같이 메시지를 전달할 수있는 방법에 대해 생각하기 시작했다 (예 : View.ShowSaveFileDialog ()). 그러나 이것이 잘못된 접근법이라고 생각합니다.

ViewModel이 대화 상자를 직접 호출해도됩니다. 그러나 ViewModel을 테스트 할 때 테스트 중에 대화 상자가 팝업되거나 모두 실패합니다 (실제로 시도하지는 않음).

따라서 테스트하는 동안 대화 상자의 “테스트”버전을 사용해야합니다. 즉, 대화 상자가 있으면 항상 인터페이스를 작성하고 대화 상자 응답을 모의하거나 기본 동작을 갖는 테스트 모의를 작성해야합니다.

컨텍스트에 따라 올바른 버전을 제공하도록 구성 할 수있는 일종의 Service Locator 또는 IoC를 이미 사용 중이어야합니다.

이 접근 방식을 사용하면 ViewModel을 계속 테스트 할 수 있으며 대화 상자를 조롱하는 방법에 따라 동작을 제어 할 수 있습니다.

도움이 되었기를 바랍니다.


답변

이를 수행하는 두 가지 좋은 방법이 있습니다. 1) 대화 서비스 (쉽고 깨끗함)와 2)보기 지원. View Assisted는 몇 가지 깔끔한 기능을 제공하지만 일반적으로 가치가 없습니다.

대화 서비스

a) 생성자 또는 일부 종속성 컨테이너와 같은 대화 서비스 인터페이스 :

interface IDialogService
{
Task ShowDialogAsync(DialogViewModel dlgVm);
}

b) IDialogService를 구현하면 창을 열거 나 (또는 ​​일부 제어를 활성 창에 주입) 주어진 dlgVm 유형의 이름 (컨테이너 등록 또는 규칙 사용 또는 DataTemplate과 관련된 ContentPresenter 사용)을 작성해야합니다. ShowDialogAsync는 TaskCompletionSource를 생성하고 .Task 속성을 반환해야합니다. DialogViewModel 클래스 자체는 닫으려고 할 때 파생 클래스에서 호출 할 수있는 이벤트가 필요하며 대화 상자보기에서 실제로 대화 상자를 닫거나 숨기고 TaskCompletionSource를 완료하는 것을 볼 수 있습니다.

b) 사용하려면 DialogViewModel 파생 클래스의 인스턴스에서 await this.DialogService.ShowDialog (myDlgVm)를 호출하십시오. 대기 상태로 돌아간 후 대화 VM에서 추가 한 속성을보고 무슨 일이 있었는지 확인하십시오. 콜백이 필요하지 않습니다.

지원보기

뷰 모델의 이벤트를 듣는 뷰가 있습니다. 이것은 기울어 진 코드와 리소스 사용을 피하기 위해 블렌드 비헤이비어로 모두 묶을 수 있습니다 (FMI, 스테로이드에 일종의 블렌딩 가능한 속성을보기 위해 “비헤이비어”클래스를 서브 클래 싱). 지금은 각보기에서 수동으로 수행합니다.

a) 커스텀 페이로드 (DialogViewModel 파생 클래스)로 OpenXXXXXDialogEvent를 만듭니다.

b) 뷰가 OnDataContextChanged 이벤트에서 이벤트를 구독하도록합니다. 이전 값! = null이고 Window의 Unloaded 이벤트에서 숨기거나 구독 취소해야합니다.

c) 이벤트가 발생하면 페이지의 리소스에있을 수있는보기가 열리도록하거나 대화 상자 서비스 접근 방식과 같이 다른 곳에서 규칙을 통해 찾을 수 있습니다.

이 방법은 더 유연하지만 더 많은 작업이 필요합니다. 많이 사용하지 않습니다. 한 가지 좋은 장점은 예를 들어보기를 실제로 탭 안에 배치 할 수 있다는 것입니다. 알고리즘을 사용하여 현재 사용자 컨트롤의 경계에 배치하거나 충분히 크지 않은 경우 큰 컨테이너가 발견 될 때까지 시각적 트리를 탐색합니다.

이를 통해 대화 상자는 실제 사용되는 장소에 가깝게 접근 할 수 있으며 현재 활동과 관련된 앱의 일부만 어둡게하고 사용자가 대화 상자를 수동으로 밀지 않고도 앱 내에서 이동할 수 있습니다. 모달 대화 상자가 다른 탭 또는 하위보기에서 열립니다.