Eigenschaften einer Navigationseigenschaft in DataGridView anzeigen (Eigenschaften auf der zweiten Ebene)

Ich versuche, mehrere Eigenschaften aus einer verknüpften Entität in einer DataGridView in einer Winforms– App anzuzeigen . Es scheint ziemlich gewöhnlich zu sein, aber ich habe Probleme, Beispiele zu finden. Es ist eine Auftragseingabeoperation. OrderSheet-Daten, die ID und das Abholdatum für den Auftrag, dann die Werbebuchungen (OrderSheetItems im folgenden Modell) im Raster. Die Auftragszeilen haben eine Navigationseigenschaft, Produkt, basierend auf der ProductId. Ich kann eine DataGridViewComboBoxColumn mit ProductId als ValueMember und ein anderes Feld als DisplayMember verwenden. Aber ich möchte mehr Daten in andere Spalten, Größe, Farbe, Material usw. aufnehmen.

OrderSheet und OrderSheetItems mit zugehörigem Produkt

Auftragserfassung

Hier ist der Code zum Laden der Daten

 try { _context.OrderSheets.Include(o => o.OrderSheetItems.Select(i => i.Product)).Load(); orderSheetBindingSource.DataSource = _context.OrderSheets.Local.ToBindingList(); } catch (Exception ex)... 

Die ProductId befindet sich in einer separaten Spalte nur zum Experimentieren, das wird später die Combobox sein. Gibt es eine Möglichkeit, die anderen Spalten an die Daten in der Produktnavigationseigenschaft von OrderSheetItem zu binden, oder muss CellValueChanged für die Produkt-ID verarbeitet werden, um die Daten in den anderen Spalten physisch festzulegen? Wenn es eine Möglichkeit gibt, die Spalten zu binden, wäre das dann per Code in OnLoad oder irgendwo im Spaltenansichts-Designer?

TIA, Mike

Sie können eine der folgenden Optionen verwenden:

  1. Verwenden Sie DataGridViewComboBoxColumn
  2. Fügen Sie der untergeordneten Entitätsteilklasse entsprechende Eigenschaften hinzu
  3. Gestalten Sie die Abfrage so, dass sie Eigenschaften der Navigationseigenschaft mithilfe von Linq
  4. Verwenden Sie das CellFormatting Ereignis, um den Wert für beschränkte Spalten für Untereigenschaften CellFormatting
  5. String-Repräsentation eines Objekts durch Überschreiben von ToString()
  6. Verwenden Sie einen benutzerdefinierten TypeDescriptor , um die Datenbindung an TypeDescriptor zu aktivieren.

Option 1 – Verwenden Sie DataGridViewComboBoxColumn

Verwendung: Dieser Ansatz ist besonders nützlich, wenn Sie das Steuerelement editierbar lassen möchten.

Bei diesem Ansatz können Sie mit DataGridViewComboBoxColumn beliebiges Feld der Navigationseigenschaft DataGridViewComboBoxColumn . Verwenden Sie mehrere DataGridViewComboBoxColumn , die an dieselbe Navigationseigenschaft mit unterschiedlichen DisplayMember gebunden sind, um mehrere DataGridViewComboBoxColumn der Navigationseigenschaft im Raster DisplayMember

ProductId in diesem Ansatz zusätzlich zu Ihrer ProductId Spalte weitere DataGridViewComboBoxColumn zum Raster hinzu und führen Sie diese Einstellungen für alle weiteren DataGridViewComboBoxColumn Spalten aus:

  • Setzen Sie DataPropertyName von ihnen auf ProductId
  • Setzen Sie die DataSource Eigenschaft derselben auf dieselbe Datenquelle, die Sie für die Hauptspalte ProductId , z. B. productBindingSource
  • Setzen Sie ValueMember von ihnen auf das gleiche ValueMember , das Sie für die Produkt-ID-Spalte festgelegt haben, es ist die Schlüsselspalte Ihrer Produkttabelle. ( ProductId )
  • Setzen Sie DisplayMember für jeden von ihnen auf eine Spalte, die Sie DisplayMember möchten, z. B. setzen Sie einen von ihnen auf Name. eins nach Preis, eins nach Größe, …. Auf diese Weise können Sie verknüpfte Entitätsfelder anzeigen.
  • Legen Sie die ReadOnly Eigenschaft von ihnen auf true . Es macht die Zelle nur lesen.
  • Wenn Sie Spalten schreibgeschützt machen möchten, legen Sie die DisplayStyle-Eigenschaft von ihnen auf Nothing . Es entfernt Dropdown-Stil.

Wenn Sie ProductId bearbeiten möchten, behalten Sie den DropDownButton auf DropDownButton . Auf diese Weise sehen Sie, wenn Sie den Wert der ProductId Spalte mit der Combobox ändern, wenn Sie die Zeile verlassen und zur nächsten Zeile wechseln, weitere Zeilen der Zeile, weitere Eigenschaften des ausgewählten Produkts. Da auch die anderen Combobox-Spalten schreibgeschützt sind und keinen Combobox-Stil haben, kann der Benutzer den Wert von ihnen nicht ändern und sie wirken nur wie eine schreibgeschützte Textfeldspalte, die andere Eigenschaften von verwandten Entitäten anzeigt.

Option 2 – Fügen Sie der untergeordneten Entitätsteilklasse entsprechende Eigenschaften hinzu

Verwendung: Dieser Ansatz ist nützlich, wenn Sie keine Werte bearbeiten müssen.

Bei diesem Ansatz können Sie Eigenschaften im Rückgabewert der untergeordneten Entitätsteilklasse der entsprechenden Eigenschaft der übergeordneten Entität definieren. Definieren Sie diese Eigenschaft beispielsweise für den Produktnamen in der Bestellposition Teilklasse:

 public string ProductName { get { if (this.Product != null) return this.Product.Name; else return string.Empty; } } 

Dann können Sie bei der Auswahl von Auftragspositionen einfach Produkte hinzufügen und die Rasterspalte an die entsprechenden Eigenschaften der Auftragsposition binden.

Option 3 – Gestalten Sie die Abfrage so, dass sie Eigenschaften der Navigationseigenschaft enthält

Verwendung: Dieser Ansatz ist nützlich, wenn Sie keine Werte bearbeiten müssen.

Sie können die Abfrage so gestalten, dass sie Eigenschaften der Navigationseigenschaft enthält. Sie können einfach ein anonymes Objekt oder einen View-Modus verwenden, zum Beispiel:

 var list = db.OrderDetails.Include("Products").Where(x=>x.OrderId==1) .Select(x=> new OrderDetailVM() { Id = x.Id, ProductId = x.ProductId, ProductName = x.Product.Name, Price = x.Product.Price }).ToList(); 

Option 4 – Verwenden Sie das CellFormatting-Ereignis, um den Wert für beschränkte Spalten für Untereigenschaften abzurufen

Verwendung: Dieser Ansatz ist nützlich, wenn Sie keine Werte bearbeiten müssen.

In diesem Ansatz können Sie das CellFormatting Ereignis von DataGridView . Sie können e.Value einfach basierend auf dem Spaltenindex e.Value . Beispielsweise:

 void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { //I Suppose you want to show product name in column at index 3 if(e.RowIndex>=0 && e.ColumnIndex==3) { var orderLineItem= (OrderLineItem)(this.dataGridView1.Rows[e.RowIndex] .DataBoundItem); if (order!= null && orderLineItem.Product != null) e.Value = orderLineItem.Product.Name); } } 

Sie können verschiedene Kriterien verwenden, um verschiedene Spalten zu bearbeiten und verschiedene Untereigenschaften anzuzeigen.

Außerdem können Sie es durch Reflektion dynamischer und wiederverwendbarer machen. Sie können den Wert der Untereigenschaft der Navigationseigenschaft mithilfe der Reflektion extrahieren. Um dies zu tun, sollten Sie eine Spalte erstellen und DataPropertyName auf Untereigenschaften wie Product.Name dann im CellFormatting Ereignis mithilfe von reflection den Wert für column CellFormatting . Hier ist ein guter Artikel von Antonio Bello über diesen Ansatz:

  • DataGridView: Wie verschachtelte Objekte gebunden werden

Option 5 – String-Repräsentation des Objekts durch Überschreiben von ToString()

Verwendung: Dieser Ansatz ist nützlich, wenn Sie keine Werte bearbeiten müssen.

Wenn Sie nur eine einzige Navigationseigenschaftsspalte ToString() möchten, können Sie einfach die ToString() Methode der Navigationseigenschaftsklasse überschreiben und einen geeigneten Wert zurückgeben. Wenn Sie eine Eigenschaft dieses Typs im Raster anzeigen, wird auf diese Weise ein benutzerfreundlicher Text angezeigt. Zum Beispiel können Sie in einer Teilklasse des Product schreiben:

 public override string ToString() { return this.Name; } 

Option 6 – Verwenden Sie einen benutzerdefinierten TypeDescriptor, um die Datenbindung an Untereigenschaften zu aktivieren

Verwendung: Dieser Ansatz ist nützlich, wenn Sie keine Werte bearbeiten müssen.

Bei diesem Ansatz können Sie einen benutzerdefinierten TypeDescriptor erstellen, mit dem Sie Daten an Eigenschaften der zweiten Ebene binden können. Hier ist ein guter Artikel von Linda Liu über diesen Ansatz:

  • Wie binden Sie eine DataGridView-Spalte an eine Eigenschaft der zweiten Ebene einer Datenquelle