2010-09-15 5 views
1

J'ai lié mon DataGrid à un DataTable et seulement quelques détails sont affichés dans la grille. Lorsque je voulais filtrer le DataGrid, j'ai créé une vue avec ItemsSource de mon DataGrid. code:Problème avec le filtrage DataGrid

Dim myView As ICollectionView = CollectionViewSource.GetDefaultView(MyDGrid.ItemsSource) 
    myView.Filter = New Predicate(Of Object)(AddressOf filterFunc1) 

Maintenant, quand je fais la recherche, les champs non affichés sont également inclus dans la recherche.

Public Function filterFunc1(ByVal obj As Object) As Boolean 
    Dim filStr As String = "*" & TextBox1.Text & "*" 
    For Each item As String In obj.Row.ItemArray 
     **If item.ToLower Like filStr.ToLower Then** 
      Return True 
     End If 
    Next 
    Return False 
End Function 

J'ai également des champs ComboBox dans le DataGrid qui sont chargés séparément des autres DataTable. Maintenant, je ne peux pas les inclure dans la recherche.

Une capture d'écran de mon application: A screenshot from my App:

Alors, comment puis-je faire une recherche qui ne comprend que le texte de la partie affichée.

EDIT: Comment puis-je ignorer la recherche dans les champs à valeurs nulles? Parce que cela provoque une exception dans mon cas.

Répondre

0

Eh bien alors ... Votre question est assez décousue et je ne comprends pas tout - peut-être que c'est pourquoi vous n'avez pas obtenu de réponse jusqu'à présent. Ignorer les champs nuls consiste simplement à ajouter une nouvelle condition dans filterFunc1 - if Convert.IsDBNull(item) then continue for (en supposant que item est un champ dans un DataRow, bien sûr).

Cependant, ce style de programmation est assez brumeux et je recommande à tout le moins d'être plus clair sur les colonnes que vous filtrez, et les types d'objets dans les colonnes. Une approche beaucoup mieux serait de mapper les données que vous obtenez de la base de données à des objets réels dans votre application - ce qui permet une programmation plus sécurisée. Je pense que le principal problème ici est que personne ne peut vraiment dire ce qui se passe là-bas à partir de quelques lignes de code parce que personne ne peut faire de suppositions sur le type d'objets qui s'y trouvent.

À propos des éléments dans la zone de liste déroulante, aucune idée de ce genre de difficultés que vous rencontrez, vous pourriez vouloir éclaircir un peu. vous pourriez maintenir, au lieu de simplement les chaînes, les structures contenant à la fois des sous-titres et les ID, comme disent

public class YourComboItem 
    public property Id as string [get/set] 
    public property Title as string [get/set] 
end class 

lient ensuite ItemsSource de votre ComboBox à une collection de ces objets récupérés dans la base de données, et mettre DisplayMemberPath à Title et ValueMemberPath à Id. Ensuite, vous pouvez utiliser SelectedValue de ComboBox pour obtenir l'ID sélectionné. Comme vous pouvez le voir, avoir des objets à la place des structures de données brutes peut avoir certains avantages.

Bien sûr, j'ai décrit l'obtention de SelectedValue directement à partir de la ComboBox, tandis qu'une architecture bien meilleure serait MVVM, avec le ViewModel contenant un ObservableCollection(Of YourComboItem) et l'ItemSource du ComboBox lié avec une liaison réelle. Vous pouvez ensuite lier l'élément SelectedItem à une propriété de votre ViewModel et disposer de l'élément dans son ensemble, y compris Id et Title, pour travailler avec sans rien savoir de votre interface utilisateur. Alternativement vous pourriez avoir un ICollectionView généré à partir de la collection d'éléments et lier l'ItemsSource à cela, alors vous auriez l'élément sélectionné dans la propriété CurrentItem d'ICollectionView.

Je vous recommande vraiment de lire sur MVVM (Model-View-ViewModel) pour faciliter votre travail avec WPF.

+0

Salut Alex, Merci pour la réponse. Premièrement, l'erreur avec DBNull est dans 'For Each'. Qu'il ne peut pas convertir un DBNull en String.Exactement où dois-je mettre la syntaxe de conversion? Deuxièmement, je n'ai pas imposé une recherche par colonne, mais une recherche sur tout le réseau. Comme vous le dites, cela pourrait être une mauvaise pratique. Je vais le changer! Et pourquoi dis-tu que je devrais récupérer seulement les champs que je vais utiliser? Et avec la chose de liste déroulante, Ma table principale avec laquelle j'ai créé la vue pour le filtre n'a pas les valeurs directement à la place de leurs identifiants. dites l'ID d'état. Maintenant, je ne peux pas rechercher les combobox avec la vue que j'ai. – sarath

+0

En utilisant Linq, vous pourriez dire 'pour chaque élément dans obj.Row.ItemArray.OfType (String)()' (c'est hors de ma tête donc je ne suis pas sûr que la syntaxe est correcte, n'ont pas fonctionné en VB depuis longtemps) . En outre, la recherche de grille complète aurait dû être évidente, oui; Dans ce cas, votre approche n'est pas si mauvaise, ce dont je me plaignais était de chercher directement sur un DataTable ... ce qui limite l'extensibilité, etc. Comme pour le ComboBox, vous avez peu de choix en plus de garder à la fois les légendes et les identifiants éléments chargés et obtenant les identifiants lors de la recherche; Je mettrai à jour ma réponse avec une suggestion. –

+0

La technique que vous avez suggérée est plus ou moins la même que la mienne. Au lieu d'avoir une classe j'utilise un DataTable qui a les champs Id et Status name. Mon DataGridComboBox est lié à cette source avec le statusId (de la table principale) lié. Mais mon problème est que ma fonction de filtre effectue la recherche sur la ** table principale ** (View) qui n'a pas les valeurs réelles (dites Medium, Low) mais id (3,6). Si tu veux, je posterai mes structures de table ici. Et je suis nouveau à .Net Alex. Je n'ai pas commencé à lire MVVM. Bien sûr :) – sarath