Reputation: 2702
I am trying to create a binding between a List
and a DataGrid
. I haven't found a working Solution in the net which is very strange.
In my little example I create a List
of objects with the two public
properties Age
and Name
:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public ObservableCollection<Person> Collection { get; set; }
public List<Person> Persons { get; set; }
private void WindowLoaded(object sender, RoutedEventArgs e)
{
this.Persons = new List<Person>();
for (int i = 0; i != 35; i++)
{
this.Persons.Add(new Person() {Age = i, Name = i.ToString()});
}
this.Collection = new ObservableCollection<Person>(this.Persons);
}
The XAML Code looks like this:
<Grid DataContext="{Binding ElementName=TestWindow, Path=.}">
<DataGrid x:Name="DataGrid" ItemsSource="{Binding Collection}" />
</Grid>
or this (both is not working):
<Grid DataContext="{Binding ElementName=TestWindow, Path=.}">
<DataGrid x:Name="DataGrid" ItemsSource="{Binding Persons}" />
</Grid>
if I use this.DataGrid.ItemsSource = this.Persons;
I see at least all the items in the list but I have to this.DataGrid.Items.Refresh()
every time the Source List
changes which is the reason why I ask the question:
What am I doing wrong? Do I need to implement INotifyPropertyChanged
?
This question must be very easy to answer but it would be also awesome to understand the mechanics.
Upvotes: 5
Views: 35530
Reputation: 17402
Okay, so the reason why you are having issues is because what happens when the window is loaded and how the data binding is set up.
The ItemsSource of the DataGrid doesn't happen until the Window has already loaded (it's getting set in your Window loaded event). So as a result, the DataGrid does not now that it's ItemsSource has changed. You can fix this by adding INotiftyProperty changed to the list itself, or, you can create the DataGrid list first, and just populate when the Window has loaded.
For example:
xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
Collection = new ObservableCollection<Person>();
InitializeComponent();
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public ObservableCollection<Person> Collection { get; set; }
public List<Person> Persons { get; set; }
private void WindowLoaded(object sender, RoutedEventArgs e)
{
this.Persons = new List<Person>();
for (int i = 0; i != 35; i++)
{
this.Persons.Add(new Person() { Age = i, Name = i.ToString() });
}
foreach (var p in Persons)
{
Collection.Add(p);
}
}
}
xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
x:Name="TestWindow"
Loaded="WindowLoaded">
<Grid DataContext="{Binding ElementName=TestWindow, Path=.}">
<DataGrid x:Name="DataGrid" ItemsSource="{Binding Collection}" />
</Grid>
</Window>
Upvotes: 5
Reputation: 2702
After a very long day of coding I was too nervous and tired. the solution is very easy:
Implement the INotifyPropertyChanged
Interface
for the Person
class:
public class Person: INotifyPropertyChanged
{
private string name;
private int age;
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
this.OnPropertyChanged("Name");
}
}
public int Age
{
get
{
return this.age;
}
set
{
this.age = value;
this.OnPropertyChanged("Age");
}
}
protected void OnPropertyChanged(string name)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
And then bind the Data with these Code behind:
this.DataGrid.DataContext = this.Persons;
For a successful Binding
you need also these XAML
Code:
<DataGrid x:Name="DataGrid" ItemsSource="{Binding}" />
The valuesin the DataGrid
will now refresh whenever the Data in one of the Person
instances changes.
Upvotes: 2
Reputation: 647
I do a similar thing a ton in Windows Forms Apps with data grid views. So maybe this can point you in the right direction... I don't have much experience with wpf.
List<Connection> connList = new List<Connection>();
//populate list somehow
BindingSource bs = new BindingSource();
bs.DataSource = connList;
DataGrid.DataSource = bs;
public class Connection
{
public string Name {get; set;}
public string Connect {get; set;}
public Connection(string n, string c)
{
Name = n;
Connect = c;
}
}
Upvotes: 0