Mostra le proprietà di una proprietà di navigazione in DataGridView (Proprietà di secondo livello)

Sto cercando di visualizzare diverse proprietà da un’entity framework correlata su un DataGridView in un’app winforms . Mi sembra abbastanza normale, ma ho difficoltà a trovare degli esempi. È un’operazione di immissione degli ordini. I dati del foglio ordini, l’ID e la data di ritiro dell’ordine, quindi gli elementi pubblicitari (OrderSheetItems nel modello seguente) nella griglia. I lineitems dell’ordine hanno una proprietà di navigazione, Product, basata su ProductId. Posso usare un DataGridViewComboBoxColumn con ProductId come ValueMember e un altro campo come DisplayMember. Ma voglio includere più dati in altre colonne, dimensioni, colore, materiale, ecc.

OrderSheet e OrderSheetItems con prodotto correlato

Inserimento ordini

Ecco il codice per caricare i dati

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

ProductId si trova in una colonna separata solo per la sperimentazione, che sarà la casella combinata in seguito. Quindi esiste un modo per associare le altre colonne ai dati nella proprietà di navigazione del prodotto di OrderSheetItem o devo gestire CellValueChanged sull’ID del prodotto per impostare fisicamente i dati nelle altre colonne? Se esiste un modo per associare le colonne, ciò avverrà tramite codice in OnLoad o da qualche parte nel progettista delle colonne della vista griglia?

TIA, Mike

Puoi utilizzare una di queste opzioni:

  1. Utilizza DataGridViewComboBoxColumn
  2. Aggiungi proprietà corrispondenti alla class parziale dell’ quadro figlio
  3. Modellare la query per includere le proprietà della proprietà di navigazione mediante Linq
  4. Utilizzare CellFormatting evento CellFormatting per ottenere il valore per le colonne limitate della proprietà secondaria
  5. Mostra la rappresentazione di stringa dell’object sovrascrivendo ToString()
  6. Utilizzare un TypeDescriptor personalizzato per abilitare l’associazione dei dati alle proprietà secondarie.

Opzione 1: utilizzare DataGridViewComboBoxColumn

Utilizzo: questo approccio sarebbe utile specialmente nei casi in cui si desidera mantenere il controllo modificabile.

In questo approccio è ansible utilizzare DataGridViewComboBoxColumn per mostrare qualsiasi campo della proprietà navigationn. Per mostrare più proprietà secondarie di campo della proprietà di navigazione nella griglia, utilizzare più DataGridViewComboBoxColumn associato alla stessa proprietà di navigazione con DisplayMember diversi

In questo approccio, oltre alla colonna ProductId , aggiungi più DataGridViewComboBoxColumn alla griglia e quindi esegui queste impostazioni per tutte le altre colonne combinate:

  • Imposta DataPropertyName di loro a ProductId
  • Impostare la proprietà DataSource di essi, esattamente sulla stessa origine dati utilizzata per la colonna ProductId principale, ad esempio productBindingSource
  • Impostalo con ValueMember sullo stesso membro del valore che hai impostato per la colonna ID prodotto, è la colonna chiave della tabella del prodotto. ( ProductId )
  • Imposta DisplayMember per ognuno di essi in una colonna che desideri mostrare, ad esempio impostane uno su Name. da uno a Price, da uno a Size, …. In questo modo puoi mostrare i campi relativi alle quadro.
  • Imposta la proprietà ReadOnly su true . Rende solo la lettura della cella.
  • Se vuoi rendere le colonne in sola lettura, DisplayStyle proprietà DisplayStyle su Nothing . Rimuove lo stile a discesa.

Se vuoi mantenere ProductId modificabile, mantieni il DisplayStyle su DropDownButton . In questo modo quando cambi il valore della colonna ProductId usando la combobox, quando lasci la riga e ti sposti alla riga successiva, vedrai altre celle di riga, mostra altre proprietà del prodotto selezionato. Inoltre, poiché le altre colonne della casella combinata sono di sola lettura e non hanno uno stile di casella combinata, l’utente non può modificarne il valore e agiscono solo come una colonna di una casella di testo di sola lettura che mostra altre proprietà dall’ quadro correlata.

Opzione 2: aggiungi proprietà corrispondenti alla class parziale dell’ quadro figlio

Utilizzo: questo approccio sarebbe utile quando non è necessario modificare i valori.

In questo approccio, è ansible definire le proprietà nel valore di ritorno della class parziale dell’ quadro figlio della proprietà corrispondente dell’ quadro padre. Ad esempio, per nome prodotto, definire questa proprietà nella class parziale dell’articolo ordine:

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

Quindi puoi semplicemente includere i prodotti quando selezioni gli articoli dell’ordine e associare la colonna della griglia alle proprietà corrispondenti dell’articolo dell’ordine.

Opzione 3: modellare la query per includere le proprietà della proprietà di navigazione

Utilizzo: questo approccio sarebbe utile quando non è necessario modificare i valori.

È ansible modellare la query per includere le proprietà della proprietà di navigazione. È ansible utilizzare un object anonimo o una modalità di visualizzazione semplicemente, ad esempio:

 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(); 

Opzione 4: utilizzare l’evento CellFormatting per ottenere il valore per le colonne limitate della proprietà secondaria

Utilizzo: questo approccio sarebbe utile quando non è necessario modificare i valori.

In questo approccio è ansible utilizzare CellFormatting evento CellFormatting di DataGridView . Puoi semplicemente impostare e.Value base all’indice della colonna. Per esempio:

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

È ansible utilizzare criteri diversi per gestire colonne diverse e mostrare diverse proprietà secondarie.

Inoltre puoi renderlo più dinamico e riutilizzabile usando il riflesso. È ansible estrarre il valore della proprietà secondaria della proprietà di navigazione mediante reflection. Per fare ciò è necessario creare una colonna e impostare DataPropertyName su proprietà secondarie come Product.Name quindi nell’evento CellFormatting , utilizzando reflection, ottenere il valore per column. Ecco un buon articolo di Antonio Bello su questo approccio:

  • DataGridView: come associare oggetti nidificati

Opzione 5: mostra la rappresentazione di stringa dell’object sovrascrivendo ToString()

Utilizzo: questo approccio sarebbe utile quando non è necessario modificare i valori.

Se vuoi mostrare solo una singola colonna di proprietà di navigazione, puoi semplicemente sovrascrivere il metodo ToString() della class di proprietà di navigazione e restituire un valore adatto. In questo modo, quando mostri una proprietà di quel tipo nella griglia, vedrai un testo amichevole. Ad esempio nella class parziale del Product , puoi scrivere:

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

Opzione 6: utilizzare un TypeDescriptor personalizzato per abilitare l’associazione dei dati alle proprietà secondarie

Utilizzo: questo approccio sarebbe utile quando non è necessario modificare i valori.

In questo approccio è ansible creare un TypeDescriptor personalizzato che consente di eseguire l’associazione dei dati alle proprietà di secondo livello. Ecco un buon articolo di Linda Liu su questo approccio:

  • Come associare una colonna DataGridView a una proprietà di secondo livello di un’origine dati