2008-10-12 7 views
2

J'ai un ListView dans WPF qui est databound à une table de base que je tire de la base de données. Le code pour le ListView est la suivante:Comment gérer les clés étrangères avec la liaison de données WPF?

<ListView Canvas.Left="402" Canvas.Top="480" Height="78" ItemsSource="{Binding}" Name="lsvViewEditCardPrint" Width="419"> 
    <ListView.View> 
     <GridView> 
     <GridViewColumn DisplayMemberBinding="{Binding Path=IdCst}">Set</GridViewColumn> 
     <GridViewColumn DisplayMemberBinding="{Binding Path=Language}">Language</GridViewColumn> 
     <GridViewColumn DisplayMemberBinding="{Binding Path=Number}">Number</GridViewColumn> 
     <GridViewColumn DisplayMemberBinding="{Binding Path=IdArt}">Artwork</GridViewColumn> 
     </GridView> 
    </ListView.View> 
</ListView> 

La colonne IdCst est une clé étrangère à une table séparée, et je voudrais afficher le champ de nom réel de cette table au lieu de simplement l'identifiant. Est-ce que quelqu'un sait comment définir une liaison de données ou existe-t-il un événement, tel que OnItemDataBound, que je pourrais intercepter pour modifier l'affichage?

Répondre

2

Ce blog post peut aider:

... Je suppose la clé étrangère doit être liée à la propriété « SelectedValue », et il y a une ItemSource que je peux lier à ma table de fait si le menu déroulant est rempli.

À ce stade, mon menu déroulant a fonctionné, mais rien n'apparaissait dans la liste déroulante. J'ai finalement remarqué une propriété 'SelectedItemPath' - J'ai supposé que ce serait le nom du champ dans mon menu déroulant que a été associé à ma clé étrangère. Sûrement assez, c'est exactement ce que c'est.

1

J'ajouter une nouvelle propriété à votre classe sous-jacente:

Public ReadOnly Property NameCst() as String 
    Get 
     Return Names.LookupName(Me.IdCst) 
    End Get 
End Property 

ou quelque chose de similaire. Notez que vous devrez probablement inclure un événement Notify Property Changed dans votre setter .IdCst pour "NameCst".

Une alternative est d'écrire un ValueConverter qui fait la recherche, mais c'est assez lourd pour quelque chose d'aussi simple.

-1

BOO YAH !!!

J'ai regardé les échantillons ici, j'ai extrait quelques-unes des références d'autres publications ici, et j'ai trouvé la réponse ... IValueConverter ... une interface qui peut être utilisée avec WPF pour convertir les valeurs au point de contraignant. C'est un peu difficile à mettre en place au début, mais pas si difficile.

La première étape consiste à créer une classe de recherche ou de conversion simple qui implémente l'interface IValueConverter. Pour ma solution, je l'ai fait:

Namespace TCRConverters 

    Public Class SetIdToNameConverter 
     Implements IValueConverter 

     Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert 
     Dim taCardSet As New TCRTableAdapters.CardSetTableAdapter 
     Return taCardSet.GetDataById(DirectCast(value, Integer)).Item(0).Name 
     End Function 

     Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack 
     Return Nothing 
     End Function 

    End Class 

End Namespace 

Note: Je ne suis pas la méthode en utilisant ConvertBack, mais il est requis par l'interface.

De là, vous devez ajouter une référence à l'espace de noms dans votre section d'en-tête XAML:

<Window x:Class="Main" Loaded="Main_Loaded" 
    // Standard references here... 
    xmlns:c="clr-namespace:TCR_Editor.TCRConverters" 
    Title="TCR Editor" Height="728" Width="1135" Name="Main"> 

Puis dans Windows.section Ressources, vous pouvez référencer le convertisseur, et dans mon cas, je créé une référence statique au CollectionViewSource qui stockera les données:

<Window.Resources> 
    <CollectionViewSource Source="{Binding Source={x:Static Application.Current}, Path=CardDetails}" x:Key="CardDetails">   
    </CollectionViewSource> 

    <c:SetIdToNameConverter x:Key="SetConverter"/>  
</Window.Resources> 

Puis finalement, dans la ListView qui faisait partie du problème initial, vous ajoutez la référence du convertisseur:

<ListView Canvas.Left="402" Canvas.Top="480" Height="78" ItemsSource="{Binding}" Name="lsvViewEditCardPrint" Width="419"> 
    <ListView.View> 
     <GridView> 
     <GridViewColumn DisplayMemberBinding="{Binding Path=IdCst, Converter={StaticResource SetConverter}}">Set</GridViewColumn> 
     // Other Columns here... 
     </GridView> 
    </ListView.View> 
</ListView> 

Ainsi, la grande partie est maintenant que lorsque je déclenche un événement qui a une carte d'identité, tout ce que je dois faire est remis à zéro régler le CollectionViewSource ...

DirectCast(Me.FindResource("CardDetails"), CollectionViewSource).Source = taCardDetails.GetDataById(CardId) 

... et tous les éléments de liaison de WPF font le reste! Ce qui est bien, c'est que je peux facilement créer d'autres convertisseurs, les ajouter à divers DataTemplates ou colonnes ailleurs dans l'application, et une fois toutes les données dans l'application WPF, les conversions peuvent être effectuées sans aller à la base de données.

+0

Remarque rapide. J'ai trouvé que compiler la classe de convertisseur avant d'ajouter tout le code de XAML semble aider à éliminer certains des "nags" qu'il vous donnera jusqu'à ce que tout soit compilé ensemble. –

+0

Désolé d'éclater votre bulle, mais ce convertisseur va frapper la base de données au moins une fois pour chaque ligne. –

+0

True true. Cependant, c'est actuellement pour un petit ensemble qui remplit certains codes de recherche. Pour un travail plus important, je fais certainement de l'optimisation, ou des données en cache locales pour minimiser ce genre d'impact. Mais c'est bon à se souvenir, merci. –

Questions connexes