I have a DataGrid with 2 static columns (Name and Age). I want to be able to dynamically add a variable number of additional columns to my DataGrid because I do not know beforehand how many additional columns there will be. I would also like for the Resulting DataGrid to be editable.
I have created a 'MyData' Class that I would like to use for my DataGrid DataContext (as an ObservableCollection of MyData Objects ).
public class MyData
{
public string NameCol { get; set; }
public string AgeCol { get; set; }
public List<string> CitiesList { get; set; }
}
The Dynamic columns Headers I would like to add are 'Country1', 'Country2',...,'CountryN'. The entries in each of these columns would be Cities in these Countries.
I have a method that takes as arguments a List of countryNames, and my DataGrid. For illustration sake, I am passing in:
List<string> CountryNames = new List<string>() {"France", "Kenya", "Japan"};
and I am calling:
AddNewColumnsAndData(CountryNames, this.dgr);
See Implementation of the AddNewColumnsAndData() method below:
public void AddNewColumnsAndData(List<string> countryNames, DataGrid dgr)
{
foreach (string countryname in countryNames)
{
Binding bdg = new Binding(); //Not sure what appropriate argument should go in the Binding Constructor
bdg.NotifyOnTargetUpdated = true;
bdg.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
bdg.Mode = BindingMode.TwoWay;//Not sure if there are other bdg Properties I should be setting
DataGridTextColumn newCityCol = new DataGridTextColumn();
newCityCol.Header = countryname;
newCityCol.Binding = bdg;
dgr.Columns.Add(newCityCol);
};
List<string> myCityList1 = new List<string>() {"Paris", "Nairobi", "Tokyo"};
List<string> myCityList2 = new List<string>() { "Strasbourg", "Mombasa", "Kyoto" };
MyData firstrow = new MyData
{
NameCol = "John",
AgeCol = "45",
CityColList = myCityList1
};
MyData secondrow = new MyData
{
NameCol = "Mary",
AgeCol = "34",
CityColList = myCityList2
};
ObservableCollection<MyData> datacollection = new ObservableCollection<MyData>();
datacollection.Add(firstrow);
datacollection.Add(secondrow);
dgr.DataContext = datacollection;
}
The XAML for my DataGrid with the Two static columns 'Name' and 'Age':
<DataGrid x:Name="dgr" ItemsSource="{Binding}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding NameCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<DataGridTextColumn Header="Age" Binding="{Binding AgeCol, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</DataGrid.Columns>
</DataGrid>
Unfortanely, this is not quite working. I am getting this error: " exception of type 'System.InvalidOperationException': Two-way binding requires Path or XPath." That tells me that I need to change the way I am setting the binding Properties.
When I comment out the 'bdg.Mode = BindingMode.TwoWay;' line, the program runs fine, however, I am not able to edit the DataGrid, also Instead of the City names underneath the Country Headers, it is pasted MyNameSpace.MyData.
My questions are: How do I set the binding appropriately so that the cells will display the city names correctly, and also, how do I make my resulting DataGrid editable?