WPF: Implementing and binding (datagrid) to a custom collection
Solution 1
Apparently, in order for AutoGenerateColumns to work in a WPF DataGrid
, your collection has to implement IItemProperties, although I've found that wrapping my collection in a (windows forms) BindingList does the trick as well (it actually wraps your collection, unlike the ObservableCollection
which just copies your collections' members into itself).
Solution 2
I think you using your knowlege of Windows Forms by writing dataGrid1.DataContext = persons; In WPF DataGrid is connected to the collection (say List) very simple: dataGrid1.ItemsSource = persons;
Solution 3
What is your MyCollection<T>
type adding over List<T>
? Either way, I would use an ObservableCollection instead (so that the UI is notified of additions/removals), and implement INotifyPropertyChanged
on your Person
class so that the UI is notified of changes to that type's property values.
EDIT
I don't think it's particularly trivial binding to your own custom collection type. You'll need to implement INotifyPropertyChanged
and INotifyCollectionChanged
on that type. This article might be of some use - http://www.e-pedro.com/2009/04/creating-a-custom-observable-collection-in-wpf/
Another option if you are using MVVM, is to use your custom collection type on your model, and use a standard ObservableCollection
on your view model and populate your view models collection from your model, then bind your grid to your view models collection.
joniba
Updated on July 09, 2022Comments
-
joniba almost 2 years
I have a custom collection that I am passing to a WPF client, which is binding the collection to a
datagrid
usingAutoGenerateColumns="True"
. The datagrid, however, is displaying empty rows (albeit the right number of empty rows). What am I doing wrong? Following is some sample code. For now I've omitted everything having to do withINotifyPropertyChanged
andINotifyCollectionChanged
because, well, I first want to have some data showing up in the grid.I should also mention that I've tried implementing the above two interfaces, but they seem to have nothing to do with this issue.
(You might not actually want to look at the sample code as there's absolutely nothing interesting about it. The collection implementation is just wrapping an inner List.)
Some random POCO:
public class Person { public string FirstName { get; set; } public string LastName { get; set; } }
Simple collection implementation:
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 }
The 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>
The window's code-behind:
public MainWindow() { InitializeComponent(); MyCollection<Person> persons = new MyCollection<Person>() { new Person(){FirstName="john", LastName="smith"}, new Person(){FirstName="foo", LastName="bar"} }; dataGrid1.DataContext = persons; }
By the way, if you change the code-behind to use a List<Person> instead of the MyCollection<Person>, everything works as expected.
EDIT:
The above code is not taken from the real situation. I have only posted it to show what I am doing in order to test my problem and to make it easier to replicate it. The actual custom collection object is quite complex and I cannot post it here. Again, I'm just trying to understand the basic concept behind what needs to be done in order for a datagrid to properly bind to a custom collection and automatically generate columns for the underlying objects.