2008-08-27 8 views
6

Je développe une application WinForms (.Net 3.5, sans WPF) où je veux être capable d'afficher des recherches de clés étrangères dans une DataGridView de databound.Liaison de données WinForms et relations de clés étrangères

Un exemple du type de relation est que j'ai une table de lignes de commande. Les lignes de commande ont une relation de clé étrangère avec les produits et les produits qui ont à leur tour une relation de clé étrangère avec ProductTypes.

Je voudrais avoir une base de données DataGridView où chaque ligne représente une ligne de commande, affichant le produit et le type de produit de la ligne. Les utilisateurs peuvent ajouter ou éditer des lignes de commande directement à la grille et choisir le produit pour la ligne de commande à partir d'une comboBoxColumn - ceci devrait alors mettre à jour la colonne producttype, montrant le type de produit pour le produit sélectionné, dans la même rangée.

Le plus proche d'un bon ajustement que j'ai trouvé jusqu'à présent est d'introduire un objet de domaine représentant une ligne de commande, puis lier le DataGridView à une collection de ces lignes de commande. Ensuite, j'ajoute des propriétés à l'objet de la ligne de commande exposant le produit et le type de produit, et génère des événements notifypropertychanged pertinents pour que tout soit à jour. Dans mon référentiel de ligne de commande, je peux ensuite relier les mappages entre cet objet de ligne de commande et les trois tables de ma base de données.

Cela fonctionne pour le côté de la liaison de données, mais avoir à coder à la main tout ce mappage OU dans le référentiel semble mauvais. Je pensais que nHibernate serait capable d'aider avec ce câblage, mais je suis aux prises avec les mappages à travers toutes les clés étrangères - ils semblent fonctionner correctement (la recherche de clé étrangère pour le produit d'une ligne de commande crée l'objet produit correct basé sur la clé étrangère) essayez de faire la liaison de données, je ne peux pas obtenir les colonnes id de databound pour mettre à jour mon produit ou les objets producttype.

Est-ce que mon approche générale est la bonne? Si c'est le cas, quelle est la bonne solution au problème de la cartographie?

Ou, y a-t-il une meilleure solution aux lignes de liaison de données incluant les recherches de clés étrangères que je n'ai même pas envisagées?

Répondre

2

Je pense que le problème que vous rencontrez est que lorsque vous liez une grille, il ne suffit pas de prendre en charge INotifyPropertyChanged, mais vous devez déclencher les événements ListChanged dans votre implémentation IBindingList et assurez-vous que vous surchargez et renvoyez true pour la propriété SupportsChangeNotification. Si vous ne retournez pas vrai pour cela, la grille ne cherchera pas à savoir si les données ont changé.

Dans .NET 2.0+, vous pouvez créer une collection générique à l'aide de la classe BindingList, ceci s'occupera de la plus grande partie (n'oubliez pas de surcharger et renvoyer true pour la propriété SupportsChangeNotification).

Si la classe que vous utilisez pour la liaison de données a une propriété qui est une collection (telle que IBindingList ou BindingList), vous pouvez lier directement la grille de clé étrangère à cette propriété.Lorsque vous configurez les liaisons dans le concepteur Forms, sélectionnez simplement la propriété de collection comme source de données pour la grille. Cela devrait "juste fonctionner". La seule partie sournoise est de s'assurer que vous gérez les collections vides ou nulles de la bonne façon.

+0

Merci Garo - qui couvre joliment ce que j'ai moi-même trouvé. La seule différence est que j'ai une colonne de clé étrangère, pas une grille. Je vais aussi mettre à jour ma réponse, ce qui me permet de savoir exactement ce qui m'a causé des problèmes - je pense que les raisons pour lesquelles j'ai mal diagnostiqué le problème à l'origine pourraient être utiles –

1

bienvenue à StackOverflow :)

Normalement ce que vous feriez est la base des informations contenues dans le menu déroulant sur deux valeurs ValueMember and DisplayMember. L'élément ValueMember est la source de la valeur réelle des contrôles (ce sera la valeur clé dans la ligne de commande), le membre d'affichage est la valeur qui est affichée à l'utilisateur au lieu de la valeur (ce sera la valeur FK).

N'y a-t-il pas une raison particulière pour laquelle vous ne pouvez pas simplement renvoyer toutes les données requises et définir ces propriétés?

0

Ma question initiale était de toute évidence pas clair, désolé. Le problème n'était pas lié à DataGridView en général, ou à l'implémentation d'un DataGridViewComboBoxColumn - comme les personnes qui ont déjà répondu correctement, qui est bien documenté sur le web.

Le problème que j'ai essayé de résoudre est l'actualisation des propriétés qui explorent les relations.Dans mon exemple de commandes, lorsque je change la valeur de la colonne "Product", la colonne "Product Type" n'est pas mise à jour - même si dans le code je définis la propriété et déclenche l'événement NotifyPropertyChanged. (En débogage, je vais à tous les bons endroits)

Après beaucoup de fouilles, je me suis rendu compte que cela ne fonctionnait même pas lorsque j'ai directement défini la propriété "Type de produit" de la source de données, plutôt que de le définir dans le "Produit "Setter.

L'autre chose que je crois m'a de nouveau sur la bonne voie est que lorsque je donne une couche de dataccess raillé, créé sous la forme principale, tout fonctionne bien.

Aussi, lorsque je copie IList faite par NHibernate à un IBindingList - tout semble à nouveau bien.

Alors le problème est que je pense avec filetage et les événements NotifyPropertyChanged étant perdu lors de l'utilisation de certaines sources de données, d'une certaine façon (voudrais pouvoir être plus précis que ça!)

Je vais garder la recherche de meilleures façons de résoudre cela que de copier l'IList sur IBindingList - peut-être que j'ai besoin d'en savoir plus sur la gestion des threads.

Modifier

J'ai développé une solution qui résout le problème et pense que je comprends ce qui me source de confusion - fondamentalement, il semble que tout sauf databinding propriété de base ne joue pas bien pour les listes qui n » est t dérivé de BindingList - dès que j'essayais de créer une base de données vers des propriétés qui ont déclenché des événements NotifyPropertyChanged chaînés, les choses se sont détraquées et j'ai perdu mes événements.

La solution d'accès aux données que j'utilise utilise une variante du modèle Rob Conery IRepository, renvoyant mes collections à une classe personnalisée, une liste SortableBindingLazyList dérivée de BindingList, implémente les méthodes de tri de base et stocke également sa liste interne en tant que requête, retardant la matérialisation de la liste.

0

Eh bien, je ne sais pas si elle est soutenue par le DataGridView, mais quand vous faites WinForms régulièrement databinding (par exemple, à une zone de texte régulière), vous pouvez utiliser chemins de propriété pour naviguer dans les relations d'objet.

Quelque chose comme ceci:

myTextBox.DataBindings.Add("Text", anOrderLine, "OrderedPart.PartNumber"); 

vaudraient voir si cela fonctionne dans votre situation aussi.

Questions connexes