2012-05-14 2 views
2

MVVM을 릴레이 명령 및 데이터 바인딩으로 사용하는 C# WPF에서 간단한 데이터베이스 응용 프로그램을 만듭니다. 데이터베이스 내용의 메모리 저장을 위해 나는 다음과 같이에서 Datagrid에 바인더 제본되는, ObservableCollection를 사용 항목을 사용자가 선택 유효성 검사 오류시 자동 데이터 바인딩을 금지하는 방법

<DataGrid ItemsSource="{Binding Path=Softwares, Mode=OneWay}" SelectedItem="{Binding Path=SoftwareSelection, Mode=TwoWay}">

를 편집하기 위해 선택할 수 있습니다. 편집을 위해 양식은 주어진 엔티티의 데이터가있는 텍스트 상자를 사용하여 열립니다. 모든 텍스트 상자가 유효하지 않고 ok 단추가 활성화되어 있지 않으므로 모든 필드가 IDataErrorInfo을 사용하여 유효성이 검사되므로 변경 사항을 컬렉션과 데이터베이스에 저장할 수 없습니다.

<TextBox Text="{Binding Name, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>

하지만 텍스트 상자에서 일부 값을 변경 한 다음 새 값이 ObservableCollection에 전파되어, 창을 닫으 경우 까다로운 부분이있다 : 예제 텍스트 상자의 모양 방법은 다음과

입니다 , 나는 그것을 원하지 않는다. 그런 행동을 피하는 방법을 알고 있습니까? 단추를 클릭 한 후에 만 ​​데이터 바인딩 작업을 싶습니다. 그렇지 않으면 databindng가 잘 작동하므로 버튼을 클릭하고 데이터베이스 및 클릭 후 컬렉션에 변경 사항이 반영됩니다. 양쪽 모두의 뷰는 다른 ViewModel에 의해 처리되고, 뷰 간의 데이터는 이벤트의 방아쇠에 의해 건네받습니다.

ItemsSource 바인딩에 DataGridUpdateSourceTrigger=Explicit에 추가하려했지만 도움이되지 않았습니다. 아마도 일부 응용 프로그램 논리가 누락 되었습니까?

도움 주셔서 감사합니다.

답변

1

이것은 대부분의 WPF 개발자가 가정의 실수를하는 곳입니다!

MVVM에서 더티 데이터는 ViewModel에 저장 될 수 있으며 이것이 VM 계층입니다. ViewModel의 관점에서 모방 한 것이므로 View에 오류가 있으므로 ViewModel도 오류가 발생합니다. 그게 전부 완벽하게 유효합니다.

그래서 질문이

어떻게 당신이 일시적/더러운 데이터가 ObservableCollection에로의 흐름을 허용하지 않습니다 유지했다가 있습니까? 모델 클래스 (MyItem가) 엔터티 클래스 \의 DAL 클래스 인 경우 ObservableCollection는 모델 클래스에 고유 한 경우

두 가지 방법 ...

  1. (MyItem를 말) 다음 \ NHibernate에 클래스 생성 래퍼 MyItemViewModelMyItem이라고 부르고 ObservableCollection<MyItem> 대신 ObservableCollection<ViewModelMyItem>을 사용합니다. 당신의 View에서

    이 방법 더티 데이터는 ViewModelMyItem 내부 될 것이며, 그것은 단지 합법적으로 다시 Save 버튼을 클릭 만 모델 클래스 (MyItem)로 비행 할 수있다. 그래서 의 Execute() 대리인에서 ViewModelMyItem의 유효성이 확인되면 ViewModelMyItem의 속성을 Item의 속성으로 복사하고 \ 복제 할 수 있습니다.

    그래서 ItemEntityType 클래스/NHibernate 클래스/WCF 클라이언트 모델 클래스의 경우, 항상 ViewModelMyItem으로 만 유효 데이터는 임시/더러운 정보가 선행 필터링되는 것입니다.

  2. 바인딩 모델 Explicit을 사용할 수 있습니다. BindingExpressions.UpdateSource()이 명시 적으로 호출되지 않으면 데이터가 Item으로 다시 흐르지 않게합니다.

    그러나 내 말에 따르면 ViewModel에 UI가 표시되지 않으므로 MVVM을 간단하게 사용할 수 있습니다. 그러나 * 첨부 된 동작 *을 사용하면 MVVM 공간에 머물러 명시 적 바인딩을 제어 할 수 있습니다!

이 정보가 도움이되는지 알려주세요.

+0

이것은 정확히 내가 찾고 있던 것입니다. – lukas

0

도메인 개체의 속성 설정자에 코드를 추가하는 것이 좋습니다. 그런 다음 NotifyPropertyChanged 처리기를 트리거하여 영상과 동기화하십시오. 이 주제에 대한

더 :
http://msdn.microsoft.com/en-us/library/ms743695.aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

+0

글쎄, 이것이 내가 실제로하는 것인데, DataGrid가있는 ViewModel에는 Software 엔티티 컬렉션이 포함되어 있습니다. 에디션 용 viewmodel에는 하나의 Software 엔티티가 들어 있으며 그 속성은 다음과 같이 채워집니다. public string Name { get {return software.Name; } { if (software.Name! = value) { software.Name = value; OnPropertyChanged ("Name");}} } 그렇지 않으면 나는 무엇을 의미하는지 이해하지 못합니다. : ( – lukas

0

명시 적으로 바인딩 모드 설정은 모델로 다시 변경을 보낼 바인딩 식 UpdateSource() 메서드를 호출하도록 요구해야한다. DataGrid의 바인딩에 명시 적으로 설정했다고 언급했기 때문에 모델에 직접 바인딩되는 모든 속성에 해당 모드가 명시 적으로 설정되어 있는지 확인해야합니다. TextBox의 Text Binding 같은 경우. 그럴 경우 문제가 해결되지만 각 대상의 BindingExpression에서 UpdateSource()를 호출해야합니다.

주류 ORM (EF, Linq to SQL 등) 중 하나를 사용하는 경우 엔티티에서 엔티티가 자동으로 INotifyPropertyChanged 및 INotifyPropertyChanging을 구현할 수 있습니다. 단일 인스턴스에 대한 참조를 공유하기 때문에 편집 내용의 모든 변경 사항이 주 뷰와 해당 인스턴스에 바인딩되는 다른 모든 요소에 반영됩니다. 더러운 대안으로, 같은 유형의 별도 인스턴스를 작성하고 창 대화 결과가 참일 때 수동으로 값을 복사 할 수 있습니다.

첫 번째 방법에서는 바인딩을 수동으로 업데이트해야하며 두 번째 방법을 사용하려면 Edit 인스턴스에서 값을 수동으로 업데이트해야합니다.

몇 가지 추가 코드를 사용하여 구체적인 접근 방식을 도울 수 있습니다.

관련 문제