2008-09-23 7 views
17

Comment pourrais-je relier l'objet suivant, Car, à un gridview? Les types primitifs sont facilement liés, mais je n'ai trouvé aucun moyen d'afficher quoi que ce soit pour Maker. Je voudrais pour cela afficher le Manufacturer.Name. Est-ce même possible?Est-il possible de lier des propriétés de type complexes à une grille de données?

Quelle serait une façon de le faire? Devrais-je stocker ManufacturerId dans Car, puis configurer un lookupEditRepository avec la liste des fabricants?

Répondre

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

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

Remplacez la méthode to string.

+0

+1 Je pense que c'est une solution solide pour les objets simples – karlipoppins

+0

Il est correct de vouloir juste une propriété, mais cela ne fonctionnera pas si vous voulez plusieurs propriétés de cet objet. –

12

Oui, vous pouvez créer un TypeDescriptionProvider pour accomplir une liaison imbriquée. Voici un exemple détaillé d'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

Le niveau de complexité pour réaliser ceci est assez élevé. Devrais-je avoir un autre ensemble de classes bindable que je convertis peut-être mes objets métier? – Xerx

+0

C'est une décision de conception. Soit vous devez créer un tas de nouvelles classes simplement à des fins de liaison ou utiliser la recette fournie dans mon message. Personnellement, je déteste encombrer ma hiérarchie de classe avec des «aides», alors j'irais avec ce dernier. –

+0

+1 L'article est exactement ce dont j'avais besoin ... – takrl

2

Il suffit d'utiliser une liste et définissez la DataMember à la chaîne « Maker.Name » et si vous voulez que le DataKeyField à utiliser l'ID de voiture juste définissez cela sur "ID".

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

Je sais qui fonctionne dans le répéteur de contrôle, au moins ...

7

La façon dont je me suis approché ce dans une application récente était de créer mes propres classes DataGridViewColumn et DataGridViewCell héritant hors de l'un des les existants tels que DataGridViewTextBoxColumn et DataGridViewTextBoxCell. En fonction du type de cellule que vous souhaitez, vous pouvez utiliser d'autres boutons tels que Button, Checkbox, ComboBox, etc. Jetez un coup d'œil aux types disponibles dans System.Windows.Forms. Les cellules traitent leurs valeurs en tant qu'objets de sorte que vous serez en mesure de transmettre votre classe Car dans la valeur de la cellule. Overriding SetValue et GetValue vous permettront d'avoir toute la logique supplémentaire dont vous avez besoin pour gérer la valeur.

Par exemple:

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

Sur la classe colonne, la principale chose que vous devez faire est de définir la CellTemplate à votre classe de cellules personnalisées.

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

En utilisant ces colonnes personnalisées/cellules du DataGridView il vous permet d'ajouter beaucoup de fonctionnalités à votre DataGridView. Je les ai utilisés pour modifier la mise en forme affichée en remplaçant GetFormattedValue pour appliquer une mise en forme personnalisée aux valeurs de chaîne.

J'ai également fait un remplacement sur Paint afin que je puisse faire une surbrillance de cellule personnalisée en fonction des conditions de valeur, en modifiant les cellules Style.BackColor à ce que je voulais en fonction de la valeur.

2

Si vous souhaitez exposer des propriétés spécifiques imbriquées en tant que cibles de liaison, la réponse 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) est plutôt bonne. L'article référencé est un peu obtus, mais ça marche.Si vous voulez simplement lier une colonne à une propriété complexe (par exemple Fabricant) et remplacer la logique de rendu, faites ce que ManiacXZ recommande, ou simplement sous-classe BoundField et fournissez une implémentation personnalisée de FormatDataValue(). Ceci est similaire à ToString(); vous obtenez une référence d'objet et vous renvoyez la chaîne que vous souhaitez afficher dans votre grille.

Quelque chose comme ceci:

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

Ajoutez juste un ManufacturerField à votre réseau, en spécifiant « Fabricant » comme champ de données, et vous êtes bon pour aller.

+0

+1 L'article lié est exactement ce dont j'avais besoin. – takrl

1

Je suppose que vous pouvez faire ce qui suit:

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

Pas vraiment ce que les gens veulent normalement faire, mais il semble plus jive avec la loi de Demeter. – jpierson

2

Voici une autre option que je suis travail:

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

est peut-être ASP.NET 4.0 spécifique, mais il fonctionne comme un charme!

22

Très bien les gars ... Cette question a été postée waaay mais je viens de trouver un moyen assez simple de faire cela en utilisant la réflexion dans l'événement cell_formatting pour aller récupérer les propriétés imbriquées.

va comme ceci:

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

Et voilà! Vous pouvez maintenant utiliser la syntaxe familière "ParentProp.ChildProp.GrandChildProp" dans le DataPropertyName pour votre colonne.

+0

A travaillé super! Merci d'avoir partagé. – Amir

+0

Très gentil, merci ^^ – Mahmoud

+0

Cela mérite plus de votes upvotes! Je ne sais pas ce qui se passe mais ça marche lol. Merci d'avoir partagé!!! –

Questions connexes