I have a databinding problem in Windows Forms.
Here's the part of the EF model that is relevant for the story:
namespace Model
{
class Person
{
[Key]
public int Id { get; set; }
public String Name { get; set; }
public virtual ICollection<Receipt> Receipts { get; set; }
}
class Receipt
{
[Key]
public int Id { get; set; }
public DateTime Timestamp { get; set; }
public double Value { get; set; }
public int PersonId { get; set; }
public virtual Person Person { get; set; }
}
}
There is a BindingSource called peopleBindingSource
that is set to class Model.Person
. In code behind, I do this:
db.People.Include(p => p.Receipts).Load();
peopleBindingSource.DataSource = db.People.Local.ToBindingList();
Textbox has its DataBindings set to peopleBindingSource
as DataSource and Name
as the property.
When I run the application, the binding navigator works correctly, showing different people as I click previous and next buttons. The textbox with the person's name is also populated correctly.
Now, here comes the problem:
On the same form, there is a DataGridView. I want to show a row for each of the Receipt of currently selected Person.
I've tried to bind dataGridView's DataSource
to Receipts
navigation property of peopleBindingSource
.
I have expected that the gridview will update its DataSource to the appropriate collection of receipts just as the textbox updates its Text property on navigation change. The setup is basicly the same.
The thing is, no error is thrown, and the grid remains empty (it doesn't even create the columns header).
Why doesn't this binding work and can this be done from within the designer? How to correctly set up binding (without programatically handling change event on peopleBindingSource and setting grid's DataSource manually from peopleBindingSource.Current)?
I have found the solution to the problem.
The thing is that DataGridView
can't bind to ICollection<Receipt>
so the solution was to change the navigation property to BindingList<Receipt>
. Then the designer showed the property correctly.