2008-09-23 10 views
17

¿Qué debo hacer para vincular el siguiente objeto, Coche, a una vista en cuadrícula?¿Es posible vincular propiedades de tipo complejo a una cuadrícula de datos?

 
public class Car 
{ 
    long Id {get; set;} 
    Manufacturer Maker {get; set;} 
} 

public class Manufacturer 
{ 
    long Id {get; set;} 
    String Name {get; set;} 
} 

Los tipos primitivos se enlazan fácilmente pero no he encontrado ninguna manera de mostrar nada para Maker. Me gustaría que muestre el Nombre del fabricante. ¿Es posible?

¿Cuál sería una forma de hacerlo? ¿Tendría que almacenar ManufacturerId en el auto también y luego configurar un lookupEditRepository con la lista de fabricantes?

Respuesta

5
public class Manufacturer 
    { 
     long Id {get; set;} 
     String Name {get; set;} 

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

Anula el método de cadena.

+0

+1 Creo que esta es una solución sólida para objetos simples – karlipoppins

+0

Está bien con solo querer una propiedad, pero no funcionará con las múltiples propiedades de ese objeto. –

12

Sí, puede crear un TypeDescriptionProvider para lograr el enlace anidado. Aquí está un ejemplo detallado de un blog de MSDN:

http://blogs.msdn.com/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-to-a-second-level-property-of-a-data-source.aspx

+1

El nivel de complejidad para lograr esto es bastante alto. ¿Debería tener otro conjunto de clases enlazables a las que pueda convertir mis objetos comerciales? – Xerx

+0

Es una decisión de diseño. O tiene que crear varias nuevas clases simplemente para propósitos vinculantes o usar la receta provista en mi publicación. Personalmente, odio abarrotar mi jerarquía de clases con 'ayudantes', así que me iría con lo último. –

+0

+1 El artículo es exactamente lo que necesitaba ... – takrl

2

sólo tiene que utilizar una lista y establece el DataMember a la cadena "Maker.Name" y si desea que el DataKeyField de usar Identificación de coche justo configurar eso para "ID".

dataGrid.DataSource = carList; 
dataGrid.DataMember = "Maker.Name"; 
dataGrid.DataKeyField = "ID"; 
dataGrid.DataBind(); 

Sé que trabaja en el control del repetidor, al menos ...

7

La forma en que me acercaba a esto en una aplicación reciente fue la de crear mis propias clases DataGridViewColumn y DataGridViewCell heredar fuera de una de las existentes como DataGridViewTextBoxColumn y DataGridViewTextBoxCell.

Dependiendo del tipo de celular que desee, puede usar otros como Button, Checkbox, ComboBox, etc. Simplemente eche un vistazo a los tipos disponibles en System.Windows.Forms.

Las celdas tratan con su valor como objetos, por lo que podrá pasar su clase de Auto al valor de la celda.

Reemplazando SetValue y GetValue le permitirá tener cualquier lógica adicional que necesite para manejar el valor.

Por ejemplo:

public class CarCell : System.Windows.Forms.DataGridViewTextBoxCell 
{ 
    protected override object GetValue(int rowIndex) 
    { 
     Car car = base.GetValue(rowIndex) as Car; 
     if (car != null) 
     { 
      return car.Maker.Name; 
     } 
     else 
     { 
      return ""; 
     } 
    } 
} 

En la clase de la columna de la cosa principal que hay que hacer es establecer la CellTemplate a su clase de celda personalizado.

public class CarColumn : System.Windows.Forms.DataGridViewTextBoxColumn 
{ 
    public CarColumn(): base() 
    { 
     CarCell c = new CarCell(); 
     base.CellTemplate = c; 
    } 
} 

Mediante el uso de estos columna personalizada/Células en el DataGridView que le permite añadir una gran cantidad de funcionalidad adicional a su DataGridView.

Los usé para alterar el formato mostrado anulando GetFormattedValue para aplicar formato personalizado a los valores de cadena.

También hice una anulación en Paint para poder hacer resaltado de celda personalizado dependiendo de las condiciones de valor, alterando las celdas Style.BackColor a lo que quería según el valor.

2

Si desea exponer propiedades anidadas específicas como objetivos vinculantes, entonces la respuesta de Ben Hoffstein (http://blogs.msdn.com/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-to-a-second-level-property-of-a-data-source.aspx) es bastante buena. El artículo al que se hace referencia es un poco obtuso, pero funciona.

Si solo desea enlazar una columna a una propiedad compleja (por ejemplo, Fabricante) y anular la lógica de representación, haga lo que ManiacXZ recomendó o solo la subclase BoundField y proporcione una implementación personalizada de FormatDataValue(). Esto es similar a anular ToString(); obtienes una referencia de objeto y devuelves la cadena que deseas mostrar en tu cuadrícula.

Algo como esto:

public class ManufacturerField : BoundField 
{ 
    protected override string FormatDataValue(object dataValue, bool encode) 
    { 
     var mfr = dataValue as Manufacturer; 

     if (mfr != null) 
     { 
      return mfr.Name + " (ID " + mfr.Id + ")"; 
     } 
     else 
     { 
      return base.FormatDataValue(dataValue, encode); 
     } 
    } 
} 

Sólo tiene que añadir ManufacturerField a su rejilla, especificando "Fabricante" como el campo de datos, y ya está bueno para ir.

+0

+1 El artículo vinculado es exactamente lo que necesitaba. – takrl

1

quiero suponer que podría hacer lo siguiente:

public class Car 
{ 
    public long Id {get; set;} 
    public Manufacturer Maker {private get; set;} 

    public string ManufacturerName 
    { 
     get { return Maker != null ? Maker.Name : ""; } 
    } 
} 

public class Manufacturer 
{ 
    long Id {get; set;} 
    String Name {get; set;} 
} 
+1

No es lo que la gente normalmente quiere hacer pero parece estar más ligado a la Ley de Demeter. – jpierson

2

Aquí hay otra opción me trabajo:

<asp:TemplateColumn 
    HeaderText="Maker"> 
    <ItemTemplate> 
      <%#Eval("Maker.Name")%> 
    </ItemTemplate> 
</asp:TemplateColumn> 

podría ser ASP.NET 4.0 específica pero funciona como un encanto!

22

Muy bien chicos ... Esta pregunta se envió a través de waaay, pero acabo de encontrar una forma bastante agradable & de hacer esto utilizando la reflexión en el evento cell_formatting para ir a recuperar las propiedades anidadas.

es la siguiente:

private void Grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) 
    { 

     DataGridView grid = (DataGridView)sender; 
     DataGridViewRow row = grid.Rows[e.RowIndex]; 
     DataGridViewColumn col = grid.Columns[e.ColumnIndex]; 
     if (row.DataBoundItem != null && col.DataPropertyName.Contains(".")) 
     { 
      string[] props = col.DataPropertyName.Split('.'); 
      PropertyInfo propInfo = row.DataBoundItem.GetType().GetProperty(props[0]); 
      object val = propInfo.GetValue(row.DataBoundItem, null); 
      for (int i = 1; i < props.Length; i++) 
      { 
       propInfo = val.GetType().GetProperty(props[i]); 
       val = propInfo.GetValue(val, null); 
      } 
      e.Value = val; 
     } 
    } 

Y eso es todo! Ahora puede usar la sintaxis familiar "ParentProp.ChildProp.GrandChildProp" en DataPropertyName para su columna.

+0

¡Funcionó muy bien! Gracias por compartir. – Amir

+0

Muy bien, gracias ^^ – Mahmoud

+0

¡Esto merece más votos favorables! No sé lo que está pasando en absoluto, pero funciona jajaja. ¡¡¡Gracias por compartir!!! –

Cuestiones relacionadas