Mostrar propiedades de una propiedad de navegación en DataGridView (propiedades de segundo nivel)

Estoy tratando de mostrar varias propiedades de una entidad relacionada en un DataGridView en una aplicación de winforms . Me parece bastante común pero me cuesta encontrar ejemplos. Es una operación de entrada de orden. Datos de hoja de pedido, la identificación y la fecha de recolección para la orden, luego las líneas de pedido (artículos de hoja de pedido en el modelo a continuación) en la cuadrícula. Los elementos de línea de pedido tienen una propiedad de navegación, Producto, basada en el IdProducto. Puedo usar un DataGridViewComboBoxColumn con ProductId como ValueMember y otro campo como DisplayMember. Pero quiero incluir más datos en otras columnas, tamaño, color, material, etc.

OrderSheet y OrderSheetItems con producto relacionado

Orden de entrada

Aquí está el código para cargar los datos

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

El ProductId está en una columna separada solo para experimentar, que será el combobox más adelante. Entonces, ¿hay alguna forma de vincular las otras columnas con los datos en la propiedad de navegación del Producto de OrderSheetItem o tengo que manejar CellValueChanged en el id del producto para establecer físicamente los datos en las otras columnas? Si hay una forma de enlazar las columnas, ¿sería eso a través del código en OnLoad o en algún lugar del diseñador de columnas de la vista de cuadrícula?

TIA, Mike

Puede usar cualquiera de estas opciones:

  1. Usar DataGridViewComboBoxColumn
  2. Agregue las propiedades correspondientes a la clase parcial de entidad hijo
  3. Forme la consulta para incluir propiedades de propiedad de navegación utilizando Linq
  4. Use el evento CellFormatting para obtener valor para columnas limitadas de propiedad secundaria
  5. Mostrar la representación de cadena del objeto anulando ToString()
  6. Utilice un TypeDescriptor personalizado para habilitar el enlace de datos a las sub propiedades.

Opción 1 – Usar DataGridViewComboBoxColumn

Uso: Este enfoque sería útil especialmente en los casos en que desee mantener el control editable.

En este enfoque, puede usar DataGridViewComboBoxColumn para mostrar cualquier campo de propiedad de navegación. Para mostrar múltiples propiedades secundarias de campo de la propiedad de navegación en la cuadrícula, utilice múltiples DataGridViewComboBoxColumn vinculados a la misma propiedad de navegación con diferentes DisplayMember

En este enfoque, adicional a su columna ProductId , agregue más DataGridViewComboBoxColumn a la grilla y luego realice estas configuraciones para todas las columnas combo adicionales:

  • Establecer DataPropertyName de ellos en ProductId
  • Establezca la propiedad DataSource de ellos, exactamente la misma fuente de datos que utilizó para la columna principal ProductId , por ejemplo productBindingSource
  • Establezca ValueMember de ellos en el mismo miembro de valor que estableció para la columna de Id del producto, es la columna clave de su tabla de productos. ( ProductId )
  • Establezca DisplayMember para cada uno de ellos en una columna que desee mostrar, por ejemplo, establezca uno de ellos en Nombre. uno a Price, uno a Size, …. De esta manera puede mostrar campos de entidades relacionadas.
  • Establezca la propiedad ReadOnly de ellos en true . Hace que la celda sea solo de lectura.
  • Si desea hacer columnas de solo lectura, configure la propiedad DisplayStyle de Nothing en Nothing . Elimina el estilo desplegable.

Si desea mantener editable ProductId , mantenga DisplayStyle en DropDownButton . De esta forma, cuando cambie el valor de la columna ProductId con el cuadro combinado, cuando salga de la fila y se mueva a la siguiente fila, verá otras celdas de la fila y mostrará otras propiedades del producto seleccionado. Además, dado que las otras columnas del cuadro combinado son de solo lectura y no tienen un estilo de cuadro combinado, el usuario no puede cambiar el valor de ellas y solo actúan como una columna de cuadro de texto de solo lectura que muestra otras propiedades de la entidad relacionada.

Opción 2: agregue las propiedades correspondientes a la clase parcial de entidad hijo

Uso: este enfoque sería útil cuando no necesita editar valores.

En este enfoque, puede definir propiedades en el valor de retorno de la clase parcial de la entidad hijo de la propiedad correspondiente de la entidad principal. Por ejemplo, para el nombre del producto, defina esta propiedad en orden clase parcial del elemento:

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

Luego, puede simplemente incluir productos al seleccionar artículos de pedido y vincular la columna de cuadrícula a las propiedades correspondientes del artículo de pedido.

Opción 3: configurar la consulta para incluir propiedades de la propiedad de navegación

Uso: este enfoque sería útil cuando no necesita editar valores.

Puede dar forma a la consulta para incluir propiedades de propiedad de navegación. Puede usar un objeto anónimo o un Modo de visualización simplemente, por ejemplo:

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

Opción 4: use el evento CellFormatting para obtener el valor de las columnas limitadas de la propiedad secundaria

Uso: este enfoque sería útil cuando no necesita editar valores.

En este enfoque, puede usar el evento CellFormatting de DataGridView . Simplemente puede establecer e.Value basado en el índice de columna. Por ejemplo:

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

Puede usar diferentes criterios para manejar columnas diferentes y mostrar diferentes propiedades secundarias.

También puedes hacerlo más dynamic y reutilizable usando la reflexión. Puede extraer el valor de la propiedad secundaria de la propiedad de navegación mediante reflexión. Para hacerlo, debe crear una columna y establecer DataPropertyName en propiedades secundarias, como Product.Name luego en el evento CellFormatting , usando reflection, obtener el valor de la columna. Aquí hay un buen artículo de Antonio Bello sobre este enfoque:

  • DataGridView: cómo vincular objetos nesteds

Opción 5: Mostrar la representación de cadena del objeto anulando ToString()

Uso: este enfoque sería útil cuando no necesita editar valores.

Si desea mostrar solo una columna de propiedad de navegación, puede anular el método ToString() de la clase de propiedad de navegación y devolver el valor adecuado. De esta manera, al mostrar una propiedad de ese tipo en la cuadrícula, verá un texto amigable. Por ejemplo, en la clase parcial de Product , puede escribir:

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

Opción 6: utilice un TypeDescriptor personalizado para habilitar el enlace de datos a propiedades secundarias

Uso: este enfoque sería útil cuando no necesita editar valores.

En este enfoque, puede crear un TypeDescriptor personalizado que le permita realizar el enlace de datos a propiedades de segundo nivel. Aquí hay un buen artículo de Linda Liu sobre este enfoque:

  • Cómo vincular una columna DataGridView a una propiedad de segundo nivel de una fuente de datos