wpf - 하기 - 윈도우 프레젠테이션




MVVM 템플릿의 좋은 예 (6)

저는 현재 Microsoft MVVM 템플릿을 사용하여 실례합니다. 자세한 예제가 실망 스럽습니다. 포함 된 ContactBook 예제는 매우 적은 명령 처리를 보여 주며 개념이 비슷하지만 약간 다른 접근법을 사용하고 여전히 복잡성이없는 MSDN Magazine 기사에서 찾은 유일한 예가 있습니다. 적어도 기본적인 CRUD 작업과 대화 / 콘텐츠 전환을 보여주는 적절한 MVVM 예제가 있습니까?

모든 사람의 제안은 정말 유용했고 좋은 자원 목록을 작성하기 시작합니다.

프레임 워크 / 템플릿

유용한 기사

스크린 캐스트

추가 라이브러리


Jason Dolinger는 MVVM에 대한 좋은 스크린 캐스트 를 만들었습니다. 언급 된 에고 르처럼 좋은 예가 하나도 없습니다. 그들은 다 끝났어. 대부분 MVVM 예제가 좋지만 복잡한 문제가 발생할 때는 그렇지 않습니다. 누구나 자신의 길을가집니다. Laurent Bugnion은 뷰 모델 간에도 통신 할 수있는 좋은 방법을 제공합니다. http://blog.galasoft.ch/archive/2009/09/27/mvvm-light-toolkit-messenger-v2-beta.aspx Cinch도 좋은 예입니다. 폴 스톨 (Paul Stovel)은 그의 마젤란 (Magellan) 프레임 워크에 대해 많은 것을 설명하는 좋은 post 을 남겼 post .


그 문제를 제 손에 맡길 때까지 나는 좌절감을 나누었습니다. IncEditor를 시작했습니다.

IncEditor ( http://inceditor.codeplex.com )는 개발자를 WPF, MVVM 및 MEF에 소개하려고하는 편집기입니다. 나는 그것을 시작했고 '테마'지원과 같은 일부 기능을 얻을 수있었습니다. 나는 WPF 나 MVVM이나 MEF의 전문가가 아니기 때문에 많은 기능을 넣을 수는 없다. 나는 너 같은 진절머리들이 그것을 더 잘 이해할 수 있도록 너희들에게 더 진지한 요청을한다.


불행히도 모든 것을 수행하는 훌륭한 MVVM 예제 앱은 없으며 일을 수행하는 데 여러 가지 다른 접근 방식이 있습니다. 먼저, 의존성 삽입, 명령, 이벤트 집계 등과 같은 편리한 도구를 제공하기 때문에 (자신 만의 다양한 패턴을 쉽게 시도 할 수 있기 때문에) 프리젠 테이션 프레임 워크 중 하나에 익숙해지기를 원할 수도 있습니다 (Prism은 적절한 선택입니다). .

프리즘 릴리스 :
Prism

그것은 꽤 괜찮은 예제 애플 리케이션 (주식 거래자)과 함께 많은 작은 예제와 방법이 포함되어 있습니다. 적어도 MVVM을 실제로 작동시키는 데 사용되는 몇 가지 공통 하위 패턴을 잘 보여줍니다. CRUD와 대화 상자 모두에 대한 예가 있습니다.

프리즘은 모든 프로젝트에 반드시 필요한 것은 아니지만 익숙해지는 것이 좋습니다.

CRUD : 이 부분은 매우 쉽습니다. WPF 양방향 바인딩을 사용하면 대부분의 데이터를 쉽게 편집 할 수 있습니다. 실제 트릭은 UI를 쉽게 설정할 수있는 모델을 제공하는 것입니다. 최소한 ViewModel (또는 비즈니스 객체)이 바인딩을 지원하기 위해 INotifyPropertyChanged 를 구현하고 속성을 UI 컨트롤에 직접 바인딩 할 수 있지만 유효성 검사를 위해 IDataErrorInfo 를 구현할 수도 있습니다. 일반적으로 CRUD를 설정하는 일종의 ORM 솔루션을 사용하면 간단합니다.

이 기사에서는 간단한 조작을 보여줍니다. http://dotnetslackers.com/articles/wpf/WPFDataBindingWithLINQ.aspx

LinqToSql을 기반으로 작성되었지만 예제와 관련이 없습니다. 중요한 것은 비즈니스 개체가 INotifyPropertyChanged (LinqToSql에 의해 생성 된 클래스)를 구현한다는 것입니다. MVVM은 그 예제의 요점은 아니지만이 경우 중요하지 않다고 생각합니다.

이 기사에서는 데이터 유효성 검사를 설명합니다.
http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx

다시 말하지만, 대부분의 ORM 솔루션은 이미 IDataErrorInfo 구현하는 클래스를 생성하고 일반적으로 사용자 지정 유효성 검사 규칙을 쉽게 추가 할 수있는 메커니즘을 제공합니다.

대부분의 ORM에 의해 생성 된 객체 (모델)를 가져 와서 그것을 저장하는 ViewModel에 랩핑하고 저장 / 삭제 명령을 내릴 수 있습니다. UI를 곧바로 모델의 속성에 바인딩 할 준비가 된 것입니다.

뷰는 다음과 같이 보일 것입니다 (ViewModel은 ORM에서 생성 된 클래스처럼 모델을 보유하는 Item 속성을가집니다).

<StackPanel>
   <StackPanel DataContext=Item>
      <TextBox Text="{Binding FirstName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
      <TextBox Text="{Binding LastName, Mode=TwoWay, ValidatesOnDataErrors=True}" />
   </StackPanel>
   <Button Command="{Binding SaveCommand}" />
   <Button Command="{Binding CancelCommand}" />
</StackPanel>

대화 상자 : 대화 상자 및 MVVM은 약간 까다 롭습니다. 대화 상자에서 Mediator 접근법의 풍미를 사용하는 것을 선호합니다.이 질문에서 조금 더 자세히 읽을 수 있습니다.
Dialogs

상당히 고전적인 MVVM이 아닌 일반적인 접근 방식은 다음과 같이 요약 할 수 있습니다.

커밋 및 취소 작업에 대한 명령을 표시하는 대화 상자 ViewModel의 기본 클래스입니다. 대화 상자를 닫을 준비가되었음을 알리는 이벤트와 모든 대화 상자에서 필요한 모든 작업을 수행합니다.

대화 상자의 일반적인보기 - 창 또는 사용자 정의 "모달"오버레이 유형 컨트롤이 될 수 있습니다. 본질적으로 뷰 모델을 덤프하는 콘텐츠 발표자이며 창을 닫는 데 필요한 배선을 처리합니다. 예를 들어 데이터 컨텍스트가 변경되면 새로운 ViewModel이 기본 클래스에서 상속되었는지 확인할 수 있습니다. 관련 close 이벤트를 등록하십시오 (핸들러가 대화 상자 결과를 지정합니다). 대체 범용 닫기 기능 (예 : X 버튼)을 제공하는 경우 ViewModel에서도 관련 닫기 명령을 실행해야합니다.

어디에서나 ViewModel에 대한 데이터 템플릿을 제공해야하는 경우 별도의 컨트롤에 캡슐화 된 각 대화 상자에 대한보기가있을 수 있으므로 매우 간단 할 수 있습니다. ViewModel의 기본 데이터 템플릿은 다음과 같이 보입니다.

<DataTemplate DataType="{x:Type vmodels:AddressEditViewModel}>
   <views:AddressEditView DataContext={Binding} />
</DataTemplate>

대화 상자보기에는 이들에 대한 액세스 권한이 있어야합니다. 그렇지 않으면 ViewModel을 표시하는 방법을 알지 못하기 때문에 공유 대화 상자 UI는 기본적으로 다음과 같습니다.

<ContentControl Content={Binding} />

암시 적 데이터 템플릿은 뷰를 모델에 매핑하지만 누가 그것을 시작합니까?

이것은 not-so-mvvm 부분입니다. 이를 수행하는 한 가지 방법은 글로벌 이벤트를 사용하는 것입니다. 내가 생각하기에 더 좋은 방법은 의존성 삽입을 통해 제공되는 이벤트 수집기 유형 설정을 사용하는 것입니다.이 방법은 이벤트가 전체 앱이 아니라 컨테이너에 전역 적으로 적용됩니다. Prism은 컨테이너 의미 체계와 종속성 삽입에 단일 프레임 워크를 사용하며 전체적으로 Unity를 꽤 좋아합니다.

일반적으로 루트 윈도우가이 이벤트에 가입하는 것이 합리적입니다. 대화 상자를 열고 제기 된 이벤트와 함께 전달되는 ViewModel에 데이터 컨텍스트를 설정할 수 있습니다.

이를 이렇게 설정하면 ViewModels에서 UI에 대해 알지 못해도 대화 상자를 열고 사용자 작업에 응답하도록 응용 프로그램에 요청하므로 대부분 MVVM이 완료된 상태로 유지됩니다.

그러나 UI가 대화를 제기해야하는 경우가 있는데, 이는 상황을 좀 더 까다롭게 만들 수 있습니다. 예를 들어 대화 상자의 위치가 버튼 위치에 따라 달라지는 경우를 고려하십시오. 이 경우 대화 상자를 열어 줄 것을 요청할 때 UI 관련 정보가 필요합니다. 일반적으로 ViewModel과 관련 UI 정보가 들어있는 별도의 클래스를 만듭니다. 불행히도 일부 커플 링은 피할 수없는 것처럼 보입니다.

요소 위치 데이터가 필요한 대화 상자를 발생시키는 버튼 핸들러의 의사 코드입니다.

ButtonClickHandler(sender, args){
    var vm = DataContext as ISomeDialogProvider; // check for null
    var ui_vm = new ViewModelContainer();
    // assign margin, width, or anything else that your custom dialog might require
    ...
    ui_vm.ViewModel = vm.SomeDialogViewModel; // or .GetSomeDialogViewModel()
    // raise the dialog show event
}

대화 상자 뷰는 위치 데이터에 바인딩하고 포함 된 ViewModel을 내부 ContentControl 전달합니다. ViewModel 자체는 여전히 UI에 대해 아무것도 모릅니다.

일반적으로 ShowDialog() 메서드의 DialogResult 반환 속성을 사용하지 않거나 대화 상자가 닫힐 때까지 스레드가 차단 될 것으로 예상합니다. 비표준 모달 대화 상자는 항상 이와 같이 작동하지는 않습니다. 복합 환경에서는 이벤트 핸들러가 어쨌든 차단되도록하지 않으려는 경우가 종종 있습니다. ViewModel을 다루는 것을 선호합니다. ViewModel의 생성자는 관련 이벤트를 구독하고 커밋 / 취소 메서드 등을 설정할 수 있으므로이 UI 메커니즘에 의존 할 필요가 없습니다.

그래서이 흐름 대신 :

// in code behind
var result = somedialog.ShowDialog();
if (result == ...

나는 사용한다:

// in view model
var vm = new SomeDialogViewModel(); // child view model
vm.CommitAction = delegate { this.DoSomething(vm); } // what happens on commit 
vm.CancelAction = delegate { this.DoNothing(vm); } // what happens on cancel/close (optional)
// raise dialog request event on the container

대부분의 대화 상자가 의사 모달 컨트롤을 차단하지 않기 때문에이 방법을 선호합니다.이 방법을 사용하면이 방법을 사용하는 것보다 더 간단 해 보입니다. 단위 테스트도 쉽습니다.



코드 프로젝트에 처음부터 간단한 MVVM 예제를 작성했습니다. 여기에는 MVVM WPF 링크 가 단계별로 나와 있습니다. 간단한 3 계층 아키텍처에서 시작하여 PRISM과 같은 프레임 워크를 사용하기 위해 졸업합니다.


Cinch 의 샘플 프로젝트는 기본적인 CRUD 및 탐색 도구를 보여줍니다. MVVM을 사용하는 것은 꽤 좋은 예이며 사용법과 동기를 설명하는 여러 부분으로 된 기사가 포함되어 있습니다.





mvvm