2011-03-08 4 views
6

J'ai une collection personnalisée que je transmets à un client WPF, qui lie la collection à datagrid en utilisant AutoGenerateColumns="True". La grille de données, cependant, affiche des lignes vides (bien que le bon nombre de lignes vides). Qu'est-ce que je fais mal? Voici un exemple de code. Pour l'instant j'ai omis tout ce qui a à voir avec INotifyPropertyChanged et INotifyCollectionChanged parce que, bien, je veux d'abord avoir des données qui apparaissent dans la grille.WPF: Implémentation et liaison (datagrid) à une collection personnalisée

Je devrais également mentionner que j'ai essayé d'implémenter les deux interfaces ci-dessus, mais elles semblent n'avoir rien à faire avec ce problème.

(Vous ne voulez pas le fait de regarder l'exemple de code, car il n'y a absolument rien d'intéressant à ce sujet La mise en œuvre de la collecte est enveloppait juste une liste intérieure..)

Certains POCO au hasard:

public class Person 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

la mise en œuvre de collection simple:

public class MyCollection<T> : IList<T> 
{ 
    private List<T> list = new List<T>(); 

    public MyCollection() 
    { 
    } 

    public MyCollection(IEnumerable<T> collection) 
    { 
     list.AddRange(collection); 
    } 

#region ICollection<T> Members 

    public void Add(T item) 
    { 
     list.Add(item); 
    } 

    public void Clear() 
    { 
     list.Clear(); 
    } 

    public bool Contains(T item) 
    { 
     return list.Contains(item); 
    } 

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     list.CopyTo(array, arrayIndex); 
    } 

    public int Count 
    { 
     get { return list.Count; } 
    } 

    public bool IsReadOnly 
    { 
     get { return false; } 
    } 

    public bool Remove(T item) 
    { 
     return list.Remove(item); 
    } 

#endregion 

#region IEnumerable<T> Members 

    public IEnumerator<T> GetEnumerator() 
    { 
     return list.GetEnumerator(); 
    } 

#endregion 

#region IEnumerable Members 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

#endregion 

#region IList<T> Members 

    public int IndexOf(T item) 
    { 
     return list.IndexOf(item); 
    } 

    public void Insert(int index, T item) 
    { 
     list.Insert(index, item); 
    } 

    public void RemoveAt(int index) 
    { 
     list.RemoveAt(index); 
    } 

    public T this[int index] 
    { 
     get { return list[index]; } 
     set { list[index] = value; } 
    } 

    #endregion 
} 

Le XAML:

<Window x:Class="TestWpfCustomCollection.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <DataGrid AutoGenerateColumns="True" 
        HorizontalAlignment="Stretch" 
        Name="dataGrid1" VerticalAlignment="Stretch" 
        ItemsSource="{Binding}" 
     /> 
    </Grid> 
</Window> 

code-behind de la fenêtre:

public MainWindow() 
{ 
    InitializeComponent(); 

    MyCollection<Person> persons = new MyCollection<Person>() 
    { 
     new Person(){FirstName="john", LastName="smith"}, 
     new Person(){FirstName="foo", LastName="bar"} 
    }; 

    dataGrid1.DataContext = persons; 
} 

Soit dit en passant, si vous modifiez le code-behind utiliser une liste < personne> au lieu de la MaCollection < personne>, tout fonctionne comme prévu.

EDIT:

Le code ci-dessus ne sont pas prises de la situation réelle. Je l'ai seulement posté pour montrer ce que je fais afin de tester mon problème et de le rendre plus facile à reproduire. L'objet de collection personnalisé réel est assez complexe et je ne peux pas le poster ici. Encore une fois, j'essaie simplement de comprendre le concept de base derrière ce qui doit être fait pour qu'une grille de données puisse se lier correctement à une collection personnalisée et générer automatiquement des colonnes pour les objets sous-jacents.

Répondre

4

Apparemment, pour AutoGenerateColumns de travailler dans un WPF DataGrid, votre collection doit mettre en œuvre IItemProperties, bien que j'ai trouvé que l'emballage ma collection dans un (Windows Forms) BindingList fait l'affaire aussi bien (il enveloppe réellement votre collection, contrairement aux ObservableCollection qui ne font que copier les membres de vos collections).

3

Quel est votre type MyCollection<T> sur List<T>? De toute façon, j'utiliserais plutôt un ObservableCollection (pour que l'interface utilisateur soit avertie des ajouts/suppressions), et implémenterais INotifyPropertyChanged sur votre classe Person afin que l'interface utilisateur soit avertie des modifications apportées aux valeurs de propriétés de ce type.

EDIT

Je ne pense pas qu'il est particulièrement contraignant trivial à votre propre type de collection personnalisée. Vous devrez implémenter INotifyPropertyChanged et INotifyCollectionChanged sur ce type. Cet article pourrait être utile - http://www.e-pedro.com/2009/04/creating-a-custom-observable-collection-in-wpf/

Une autre option si vous utilisez MVVM, est d'utiliser le type de votre collection personnalisée sur votre modèle, et d'utiliser un ObservableCollection standard sur votre modèle de vue et remplir votre vue collection de modèles à partir de votre modèle , puis liez votre grille à votre collection de modèles de vue.

+0

Désolé, je n'étais probablement pas clair dans ma question. L'objet MyCollection était uniquement destiné à décrire le problème. La collection personnalisée que j'utilise est complètement différente. J'essaie juste de comprendre comment faire ce travail. Mettra à jour la question. – joniba

+0

Réponse juste mise à jour – devdigital

+0

Drôle, toutes les routes mènent juste à ce même article. En fait, j'ai suivi les instructions de l'article auquel vous étiez lié. Et cela m'a conduit au phénomène que j'ai mentionné dans la question. Quant à l'utilisation du view-model en tant qu'intermédiaire, c'est exactement ce que je voulais éviter en implémentant ma propre collection. C'est la mise en œuvre actuelle, mais je veux réduire la quantité de code de liaison en cours. En outre, j'ai délibérément voulu éviter le sujet de INotify___ parce que je veux d'abord voir que les AutoGenerateColumns fonctionnent dans la grille de données. – joniba

3

Je pense que vous utilisez votre connaissance de Windows Forms en écrivant dataGrid1.DataContext = persons; Dans WPF DataGrid est connecté à la collection (disons Liste) très simple: dataGrid1.ItemsSource = personnes;

Questions connexes