2010-03-11 28 views
9

Tôi có hai lớp: EmployeeEmployeeGridViewAdapter. Employee bao gồm một số loại phức tạp. EmployeeGridViewAdapter kết thúc tốt đẹp một đơn Employee và hiển thị các thành viên của nó dưới dạng tập hợp các loại hệ thống để DataGridView có thể xử lý hiển thị, chỉnh sửa, v.v.Đồng bộ hóa bộ sưu tập các đối tượng được bao bọc với bộ sưu tập các vật chưa được tháo

Tôi đang sử dụng hỗ trợ dựng sẵn của VS để chuyển POCO thành nguồn dữ liệu đính kèm vào một đối tượng BindingSource. Khi tôi đính kèm các DataGridView vào BindingSource nó tạo ra các cột dự kiến ​​và trong thời gian chạy tôi có thể thực hiện các hoạt động CRUD dự kiến. Tất cả là tốt cho đến nay.

Vấn đề là tập hợp các bộ điều hợp và tập hợp nhân viên không được đồng bộ hóa. Vì vậy, tất cả các nhân viên tôi tạo ra một thời gian chạy không bao giờ được tiếp tục tồn tại. Dưới đây là một đoạn mã mà tạo ra bộ sưu tập của EmployeeGridViewAdapter 's:

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

Khá thẳng về phía trước nhưng tôi không thể tìm ra cách để đồng bộ hóa những thay đổi về bộ sưu tập gốc. Tôi tưởng tượng chỉnh sửa đã được xử lý bởi vì cả hai bộ sưu tập tham chiếu cùng một đối tượng nhưng tạo nhân viên mới và xóa nhân viên không xảy ra vì vậy tôi không thể chắc chắn.

+0

@Kenneth: Bạn đã làm gì để giải quyết vấn đề của mình? – VoidDweller

+0

Cách áp dụng giải pháp ObservableViewModelCollection cho http://stackoverflow.com/questions/1256793/mvvm-sync-collections. –

Trả lời

1

Vấn đề đầu tiên có vẻ là bạn đang tạo danh sách mới và dữ liệu ràng buộc với điều đó. Khi bạn thêm các phần tử, chúng sẽ được thêm vào bộ sưu tập nhưng danh sách nhân viên ban đầu của bạn vẫn chưa được sửa đổi.

Để tránh điều này, bạn nên cung cấp lớp sưu tập tùy chỉnh sẽ di chuyển các thay đổi về danh sách nhân viên cơ bản hoặc kết nối các sự kiện thích hợp (để thực hiện di chuyển khi chèn/xóa) trước khi dữ liệu ràng buộc với nó.

Để tránh một số vấn đề khác với bộ sưu tập có thể chỉnh sửa ràng buộc với lưới, bạn nên triển khai giao diện ràng buộc dữ liệu, như được nêu bên dưới. Sự hiện diện của các giao diện này cho phép các điều khiển trực quan thông báo cho bộ sưu tập cơ bản về các hành động như "chèn bị hủy" (khi người dùng hủy đăng nhập bản ghi mới) và tương tự cho phép thông tin chảy theo hướng ngược lại (cập nhật giao diện người dùng khi thu thập hoặc cá nhân) mục thay đổi).

Trước tiên, bạn sẽ muốn triển khai ít nhất IEditableObject, INotifyPropertyChanged và IDataErrorInfo trên các mục riêng lẻ trong tập hợp dữ liệu ràng buộc, trong trường hợp của bạn sẽ là lớp EmployeeGridViewAdaper.

Ngoài ra, bạn muốn bộ sưu tập của mình triển khai ITypedList và INotifyCollectionChanged. BCL chứa một triển khai BindingList cung cấp một điểm khởi đầu tốt cho việc này. Đề nghị sử dụng điều này thay vì Danh sách đơn giản.

Tôi có thể đề xuất Data Binding with Windows Forms 2.0 để có phạm vi phủ sóng đầy đủ về chủ đề này.

3

Bạn cũng có thể xem xét sử dụng System.Collections.ObjectModel.ObservableCollection và kết nối với sự kiện CollectionChanged. Nó có thể trông như thế này.

 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; 
       } 
      }; 

Mã giả định sau đây bằng cách sử dụng câu lệnh.

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

Nếu bạn cần giao diện IList bạn cũng có thể sử dụng System.ComponentModel.BindingList và dây lên nó ListChanged sự kiện. Nó có thể trông như thế này.

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; 
       } 
      }; 

Mã giả sử tuyên bố sau đây sử dụng.

using System.ComponentModel; 
Các vấn đề liên quan