2010-03-11 29 views
9

Ich habe zwei Klassen: Employee und EmployeeGridViewAdapter. Employee besteht aus mehreren komplexen Typen. EmployeeGridViewAdapter wickelt eine einzelnes Employee und setzt seine Mitglieder als abgeflachte Satz von Systemtypen so ein Datagridview Anzeige handhaben kann, Bearbeitung usw.Synchronisieren einer Sammlung umgebrochener Objekte mit einer Sammlung unverpackter Objekte

mir VS des eingebaute Unterstützung unter Verwendung einen POCO in eine Datenquelle zum Drehen, die mich dann an ein BindingSource Objekt anhängen. Wenn ich die DataGridView an die BindingSource anschließe, erstellt es die erwarteten Spalten, und zur Laufzeit kann ich die erwarteten CRUD-Operationen ausführen. Bis jetzt ist alles gut.

Das Problem ist die Sammlung von Adaptern und die Sammlung von Mitarbeitern wird nicht synchronisiert. So werden alle Mitarbeiter, die ich eine Laufzeit erstellen nie dauerhaft erhalten. Hier ist ein Ausschnitt aus dem Code, der die Sammlung von EmployeeGridViewAdapter ‚s erzeugt:

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

ziemlich geradlinig, aber ich kann nicht herausfinden, wie sich Änderungen zu synchronisieren, wieder auf die ursprüngliche Sammlung. Ich kann mir vorstellen, dass Änderungen bereits bearbeitet werden, weil beide Sammlungen auf dieselben Objekte verweisen, aber das Erstellen neuer Mitarbeiter und das Löschen von Mitarbeitern geschieht nicht, so dass ich mir nicht sicher sein kann.

+0

@Kenneth: Was haben Sie getan, um Ihr Problem zu lösen? – VoidDweller

+0

Wie wird die ObservableViewModelCollection-Lösung auf http://stackoverflow.com/questions/1256793/mvvm-sync-collections angewendet? –

Antwort

1

Das erste Problem scheint zu sein, dass Sie eine neue Liste und Datenbindung zu diesem erstellen. Wenn Sie Elemente hinzufügen, werden diese zur Sammlung hinzugefügt, aber Ihre ursprüngliche Mitarbeiterliste bleibt unverändert. Um dies zu vermeiden, sollten Sie entweder eine benutzerdefinierte Erfassungsklasse bereitstellen, die Änderungen zurück in die zugrunde liegende Mitarbeiterliste migriert, oder die entsprechenden Ereignisse verdrahten (um die Migration beim Einfügen/Löschen durchzuführen), bevor die Daten an sie gebunden werden.

Um eine Reihe anderer Probleme beim Binden von bearbeitbaren Sammlungen an Raster zu vermeiden, sollten Sie die Datenbindungsschnittstellen wie unten beschrieben implementieren. Das Vorhandensein dieser Schnittstellen ermöglicht es den visuellen Steuerelementen, die zugrunde liegende Sammlung über Aktionen wie "Einfügung abgebrochen" zu benachrichtigen (wenn Benutzer die Eingabe eines neuen Datensatzes abbricht) und in ähnlicher Weise Informationen in die entgegengesetzte Richtung fließen zu lassen (UI bei Erfassung oder Einzelperson aktualisieren) Einträge ändern sich).

Zuerst sollten Sie mindestens IEditableObject, INotifyPropertyChanged und IDataErrorInfo für die einzelnen Elemente in einer datengebundenen Auflistung implementieren, was in Ihrem Fall die EmployeeGridViewAdaper-Klasse wäre.

Darüber hinaus möchten Sie, dass Ihre Sammlung ITypedList und INotifyCollectionChanged implementiert. Die BCL enthält eine BindingList-Implementierung, die einen guten Ausgangspunkt dafür bietet. Empfehlen Sie diese anstelle der einfachen Liste.

Ich kann Data Binding with Windows Forms 2.0 für eine umfassende Berichterstattung zu diesem Thema empfehlen.

3

Sie könnten auch in Betracht ziehen, System.Collections.ObjectModel.ObservableCollection zu verwenden und es ist CollectionChanged Event zu verkabeln. Es könnte in etwa so aussehen.

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

Code nimmt die folgenden using-Anweisungen an.

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

Wenn Sie die IList Schnittstelle benötigen könnten Sie auch System.ComponentModel.BindingList und Draht aufbrauchen es ListChanged Ereignis ist. Es könnte so aussehen.

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

Code nimmt die folgende using-Anweisung an.

using System.ComponentModel; 
Verwandte Themen