2011-12-13 9 views
0

저는 INotifyPropertyChanged를 구현하는 Item 객체에 바인딩되는 DataGrid를 보유하고 있습니다.MVVM Datagrid가보기 및 모델에서 업데이트되었습니다.

ViewModel에서 Item 개체를 업데이트하는 외부 장치 서비스의 변경 내용을 구독합니다. DataGrid를 편집 할 수 있으므로보기에서 항목을 변경할 수도 있습니다. 값은 디바이스에 기록되어야하지만 디바이스 쓰기가 실패 할 수 있기 때문에 뷰에서 아직 갱신되지 않아야합니다. 성공하면 장치는 이미 구독 한 이벤트를 발행합니다.

내 관심사 중 일부는 다음과 같습니다.

장치 서비스, ViewModel 또는 Item 개체에서 쓰기는 어디서 호출해야합니까? 디바이스에서 이벤트를 수신 할 때까지 편집 후에 DataGrid에 표시된 값이 "되돌릴"수 있도록하는 방법은 무엇입니까?

어떤 생각

  1. 는 항목 객체의 경우, 다음 항목 객체는 더 이상 DTO 없지만, 오히려 ViewModel을 것 같아요. 따라서 동일한보기 (사용자 정의)에 대해 두 개의보기 모델을 갖게됩니다. 하나는 사용자 정의 컨트롤이고 다른 하나는 DataGrid의 항목입니다. 그것은 뷰 모델에 대한 나의 이해와 맞지 않습니다. 그러나 아마도 그것은 틀린가? 그런 다음 항목이 값 (사용자 별) 또는보기 모델 (장치 서비스 별)에서 업데이트되었는지 어떻게 알 수 있습니까?

  2. ViewModel은 Item 객체의 PropertyChanged를 구독합니다. 값이 View에서 변경되었는지 감지하기 위해 ViewModel은 PropertyChanged의 등록을 취소하거나 서비스에서 이벤트를받을 때 플래그를 설정할 수 있습니다. 그것은 울퉁불퉁하지만 작동 할 것이다. 아마도 두 개의 속성, ViewValue 및 ServiceValue를 만들어야합니다. ViewModel은 ServiceValue를 업데이트하고 ViewValue에 가입해야합니다. ViewValue를 읽은 후에 ViewValue를 ServiceValue로 되돌릴 수 있습니다.

  3. 보기는 CellEditEnding을 처리하고 뷰 모델

답변

2

에 대해서는 포인트 1) 통지 : 예, UI보다는 DTO에 바인드 뷰 모델을 사용합니다. MVVM의보기에서 데이터를 분리하는 데 도움이되는 주요 아이디어입니다.

포인트 2)와 3)에 대해서는 공통 기본 클래스의 ViewModels에 IEditableObject 인터페이스를 구현하는 것이 좋습니다.

이 인터페이스는 방법 BeginEdit(), CancelEdit(), and EndEdit()을 제공합니다. 이러한 방법을 사용하면 수정되는 개체와 변경 사항을 제출할시기를 명확하고 쉽게 읽을 수 있습니다. 서비스 또는 데이터베이스로

또한 이러한 메서드를 구현하면 앞서 언급 한 "ViewValue"및 "ServiceValue"와 같은 다른 데이터 버전을 처리 할 수있는 메커니즘이 제공됩니다. BeginEdit() 메서드가 호출 될 때 폴백으로 ServiceValue의 로컬 복사본을 만들고 CancelEdit() 메서드가 호출되면이 로컬 폴백 값을 호출 할 수 있습니다. EndEdit()이 호출되면 서비스에 값을 다시 제출할 시간이고 이후에 성공하면 해당 로컬 임시 값의 현재 값을 새 폴백으로 저장합니다.이것은 "가장 좋은 방법은"경우

편집 나는 확실하지 않다 포인트 1에 대한 답변)

을 추가 할 수 있지만, 적어도이 우리 직장에서의 것입니다.

일반적으로 ViewModel은 특정보기에 대한 모든 정보가 포함 된보기 당 하나의 ViewModel을 갖도록 구성됩니다. 이것을 "메인 ViewModel"이라고합시다. 뷰의 계층 구조가 필요한 경우 동일한 계층 구조를 따르는 ViewModel의 계층 구조를 구현합니다.

여러분의 경우 DataGrid를 주보기 내에 포함 된 UserControl에 넣습니다. 주 ViewModel은 DataGrid에 필요한 데이터를 다시 보유하는 다른 ViewModel을 보유합니다. 이 ViewModel은 해당 DataGrid-UserControl의 DataContext로 설정됩니다. 이렇게하면 깨끗한 하나의 ViewModel/View 분리가 유지됩니다.

그런 다음 DataGrid의 데이터 서식을 Templates으로 구성 할 수 있습니다.

+0

IEditableObject는 좋게 들리 겠지만 좀 살펴 보겠습니다. 포인트 1에 관해, 아마도 나는 충분히 명확하지 않았다. 내 관심사는 "동일한"보기에 대한 두 개의보기 모델, 하나는 창, 하나는 창에있는 DataGrid의 항목에 대한 것입니다. 나는 viewmodel이 window/usercontrol에 속하며 DataGrid의 항목이 아니라고 생각합니다. 하지만 내 생각이 틀렸어? – Karsten

+0

또한 DataGrid에 바인드 한 entity의 IEditableObject 인터페이스를 구현할 수 있습니다. 그것은 훨씬 더 많은 유연성을 줄 것입니다. –

+0

Hmm은 DataGrid를 사용자 정의 컨트롤에 두는 것에 대해 중재합니다. 좋은 명확한 이름이 좋으므로 사용자 컨트롤의 이름을 지정하고 모델을 보는 방법을 알고 싶습니다. – Karsten

1

1) 외부 데이터 서비스에서 DTO 클래스를 업데이트해도 뷰 모델이 만들어지지 않습니다. DTO는 모델 또는 비즈니스 오브젝트 계층의 일부입니다. 이 작업은 프레젠테이션 (보기 및 뷰 모델)과 저장소 계층 (데이터베이스)간에 데이터를 전달하고 필요에 따라 유효성 검사를 수행하는 것입니다. 외부 (비 - 뷰) 서비스에 의해 업데이트되는 것은 해당 역할의 범위 내에 있습니다. 윈도우 또는 사용자 정의 컨트롤 하나당 VM에 대한 귀하의 의견은 틀리지 않습니다 - VM은 컨트롤별로가 아니라 뷰별로 할당됩니다 (여러 뷰에 대해 동일한 VM 클래스를 재사용 할 수는 있지만). 뷰가 VM에서 바인드하는 DTO의 인스턴스가 있어야합니다. 그것이 VM의 임무입니다. 모델의 필수 부분을 구성, 관리 및 표시 할 수 있습니다.

질문에서 언급 한 것처럼 DTO가 업데이트의 출처를 알고있게하려면보기 또는 서비스에서 온 것인지를 나타내는 플래그를 추가하고 필요에 따라 설정할 수 있습니다. 또는 공용 메서드를 통해 DTO를 업데이트하고 뷰가 속성에 직접 바인딩되도록 할 수 있습니다. 디자인에 따라 플래그를 설정하는 것보다이 옵션을 사용하는 것이 훨씬 쉽지는 않습니다.

2) IEditableObject은 다른 대답에서 언급했듯이 좋은 선택입니다. DTO에서 서비스 및 뷰 데이터의 백업을 모두 수행하지 않아도되며 객체 크기를 효과적으로 3 배로 늘릴 수 있습니다 (얇은 래퍼라면 DTO 일 필요가 있습니다). 은 되돌릴 때 사용할 버전을 선택하는 옵션을 제공하기 때문에 데이터 버전으로 되돌릴 수 있어야합니다. 모델 대신 VM에서 주변 데이터를 유지해야합니다. . 어떤 종류의 프리젠 테이션이나 사용자 상호 작용 결정을 포함하지 않는 옵션이 필요한 이유를 생각할 수 없습니다. 데이터 기반 복귀는 항상 결정 론적이되도록 설계되어야합니다.

3) 다시 IEditableObject. 뷰는 뷰 모델에 알리지 않아야합니다. VM을 모르는 상태 여야합니다 (참조가 없습니다). 이렇게하면 두 레이어 간의 커플 링이 느슨해지며 애플리케이션의 유연성이 향상됩니다. 일반적으로 뷰를 처리하는 데 전적으로 권한을 부여한 컨트롤러 클래스를 사용하여이 작업을 수행합니다. 뷰를 열면 새 VM 인스턴스가 만들어지고 뷰의 DataContext을 가리 킵니다.

관련 문제