2010-03-11 9 views
9

두 클래스가 있습니다 : EmployeeEmployeeGridViewAdapter입니다. Employee은 여러 가지 복잡한 유형으로 구성됩니다. EmployeeGridViewAdapter 등, 하나의 Employee를 래핑하고 DataGridView를 편집, 표시 처리 할 수 ​​있도록 시스템 유형의 평탄화 된 세트로 멤버를 노출래핑 된 객체의 컬렉션을 래핑되지 않은 객체의 컬렉션과 동기화

내가 다음 데이터 소스에 POCO 터닝 VS의 내장 지원을 사용하고

BindingSource 개체에 첨부하십시오. DataGridViewBindingSource에 첨부하면 예상되는 열이 만들어지고 런타임에 예상 한 CRUD 작업을 수행 할 수 있습니다. 지금까지는 모두 좋았습니다.

문제는 어댑터 모음이며 직원 컬렉션은 동기화되지 않습니다. 따라서 런타임을 작성한 모든 직원은 절대로 지속되지 않습니다. 여기 EmployeeGridViewAdapter 년대의 컬렉션을 생성하는 코드의 조각이다 :

 var employeeCollection = new List<EmployeeGridViewAdapter>(); 
     foreach (var employee in this.employees) 
     { 
      employeeCollection.Add(new EmployeeGridViewAdapter(employee)); 
     } 
     this.view.Employees = employeeCollection; 

꽤 정직하지만 나는 원래 컬렉션에 변경 내용을 동기화하는 방법을 알아낼 수 없습니다. 두 개의 콜렉션 모두 동일한 객체를 참조하지만 새 직원을 생성하고 직원 삭제가 발생하지 않으므로 편집이 이미 처리 된 것 같아 확신 할 수 없습니다.

+0

@Kenneth : 문제를 해결하기 위해 무엇을 했습니까? – VoidDweller

+0

ObservableViewModelCollection 솔루션을 http://stackoverflow.com/questions/1256793/mvvm-sync-collections에 적용하는 방법은 어떻습니까? –

답변

1

첫 번째 문제는 새 목록과 데이터 바인딩을 만드는 것입니다. 요소를 추가 할 때 컬렉션에 추가되지만 원본 직원 목록은 수정되지 않습니다.

이 문제를 방지하려면 변경 사항을 기본 직원 목록으로 마이그레이션하는 사용자 지정 컬렉션 클래스를 제공하거나 데이터 바인딩 전에 해당 이벤트를 연결 (삽입/삭제시 마이그레이션 수행)해야합니다.

편집 가능한 컬렉션을 그리드에 바인딩하는 데 따른 여러 가지 문제를 피하려면 아래에 설명 된대로 데이터 바인딩 인터페이스를 구현해야합니다. 이러한 인터페이스가 있으면 시각적 컨트롤이 기본 컬렉션에 "삽입 취소"(사용자가 새 레코드의 항목을 중단하는 경우)와 같은 작업을 알리고 마찬가지로 정보가 반대 방향으로 흐를 수 있습니다 (컬렉션 또는 개인 항목이 변경됨).

먼저, 데이터 바인딩 된 컬렉션의 각 항목에 적어도 IEditableObject, INotifyPropertyChanged 및 IDataErrorInfo를 구현해야합니다.이 경우에는 EmployeeGridViewAdaper 클래스가됩니다.

또한 컬렉션에 ITypedList 및 INotifyCollectionChanged를 구현해야합니다. BCL에는 BindingList 구현이 포함되어있어이를위한 좋은 출발점을 제공합니다. 일반 목록 대신 이것을 사용하는 것이 좋습니다.

Data Binding with Windows Forms 2.0을 권장 할 수 있습니다.

3

또한 System.Collections.ObjectModel.ObservableCollection을 사용하여 연결하고 CollectionChanged 이벤트를 배선하는 것이 좋습니다. 이런 식으로 보일 수 있습니다.

 ObservableCollection<EmployeeAdapter> observableEmployees = 
        new ObservableCollection<EmployeeAdapter>(); 

     foreach (Employee emp in employees) 
     { 
      observableEmployees.Add(new EmployeeAdapter(emp)); 
     } 

     observableEmployees.CollectionChanged += 
      (object sender, NotifyCollectionChangedEventArgs e) => 
      { 
       ObservableCollection<EmployeeAdapter> views = 
         sender as ObservableCollection<EmployeeAdapter>; 
       if (views == null) 
        return; 
       switch (e.Action) 
       { 
        case NotifyCollectionChangedAction.Add: 
         foreach (EmployeeAdapter view in e.NewItems) 
         { 
          if (!employees.Contains(view.Employee)) 
           employees.Add(view.Employee); 
         } 
         break; 
        case NotifyCollectionChangedAction.Remove: 
         foreach (EmployeeAdapter view in e.OldItems) 
         { 
          if (employees.Contains(view.Employee)) 
           employees.Remove(view.Employee); 
         } 
         break; 
        default: 
         break; 
       } 
      }; 

코드는 다음 사용 문을 가정합니다. 당신이 IList 인터페이스가 필요한 경우가 ListChanged 이벤트의 최대

using System.Collections.ObjectModel; 
using System.Collections.Specialized; 

당신은 또한 System.ComponentModel.BindingList 및 와이어를 사용할 수 있습니다. 이렇게 보일 수 있습니다.

BindingList<EmployeeAdapter> empViews = new BindingList<EmployeeAdapter>(); 

foreach (Employee emp in employees) 
{ 
    empViews.Add(new EmployeeAdapter(emp)); 
} 

empViews.ListChanged += 
     (object sender, ListChangedEventArgs e) => 
      { 
       BindingList<EmployeeAdapter> employeeAdapters = 
         sender as BindingList<EmployeeAdapter>; 
       if (employeeAdapters == null) 
        return; 

       switch (e.ListChangedType) 
       { 
        case ListChangedType.ItemAdded: 
         EmployeeAdapter added = employeeAdapters[e.NewIndex]; 
         if (!employees.Contains(added.Employee)) 
          employees.Add(added.Employee); 
         break; 
        case ListChangedType.ItemDeleted: 
         EmployeeAdapter deleted = employeeAdapters[e.OldIndex]; 
         if (employees.Contains(deleted.Employee)) 
          employees.Remove(deleted.Employee); 
         break; 
        default: 
         break; 
       } 
      }; 

코드는 다음 사용 문을 가정합니다.

using System.ComponentModel; 
관련 문제