All, I am creating a data set which is 'bound' to a DataGrid
at run-time. I pull in some data that is used to build a class which is inheriting from ObservableCollection<T>
. The class in question is
public class ResourceData : ObservableCollection<ResourceRow>
{
public ResourceData(List<ResourceRow> resourceRowList) : base()
{
foreach (ResourceRow row in resourceRowList)
Add(row);
}
}
public class ResourceRow
{
private string keyIndex;
private string fileName;
private string resourceName;
private List<string> resourceStringList;
public string KeyIndex
{
get { return keyIndex; }
set { keyIndex = value; }
}
public string FileName
{
get { return fileName; }
set { fileName = value; }
}
public string ResourceName
{
get { return resourceName; }
set { resourceName = value; }
}
public List<string> ResourceStringList
{
get { return resourceStringList; }
set { resourceStringList = value; }
}
}
I return a ResourceData
object from a method called BuildDataGrid()
, defined as
private ResourceData BuildDataGrid(Dictionary<string, string> cultureDict)
{
// ...
}
I then set the DataGrid
's ItemSource
to this ResourceData
object via
dataGrid.ItemSource = BuiltDataGrid(cultureDictionary);
however, this is not correctly expanding the ResourceStringList
within ResourceRow
. I get displayed:
My question is: How can I amend my ResourceRow
class to allow the DataGrid
to automatically read and display the contents of a ResourceData
object? I want to display each item in the ResourceStringList
in a separate column.
Thanks for your time.
Here's my solution - I changed up the control, rather than the ResourceRow but I think it achieves what you're looking for.
We just create a DataGrid with design-time columns in the xaml, and then add the run-time columns dynamically in the control's constructor. A couple things to keep in mind - we're assuming the first row of the ResourceData is a good model for all of the rows since this is the one we use to determine the columns to add to the datagrid in the constructor. Second, Since ResourceRow does not implement INotifyPropertyChanged, we won't get updated values for the columns that come from the ResourceStringList - but that can easily be changed.
The Code-behind:
namespace WpfApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ResourceData data = GetData();
_dataGrid.ItemsSource = data;
for (int i = 0; i < data[0].ResourceStringList.Count; i++)
{
DataGridTextColumn column = new DataGridTextColumn();
column.Binding = new Binding(string.Format("ResourceStringList[{0}]", i));
column.Header = string.Format("dynamic column {0}", i);
_dataGrid.Columns.Add(column);
}
}
public ResourceData GetData()
{
List<ResourceRow> rows = new List<ResourceRow>();
for (int i = 0; i < 5; i++)
{
rows.Add(new ResourceRow() { KeyIndex = i.ToString(), FileName = string.Format("File {0}", i), ResourceName = string.Format("Name {0}", i), ResourceStringList = new List<string>() { "first", "second", "third" } });
}
return new ResourceData(rows);
}
}
public class ResourceData : ObservableCollection<ResourceRow>
{
public ResourceData(List<ResourceRow> resourceRowList)
: base()
{
foreach (ResourceRow row in resourceRowList)
Add(row);
}
}
public class ResourceRow
{
private string keyIndex;
private string fileName;
private string resourceName;
private List<string> resourceStringList;
public string KeyIndex
{
get { return keyIndex; }
set { keyIndex = value; }
}
public string FileName
{
get { return fileName; }
set { fileName = value; }
}
public string ResourceName
{
get { return resourceName; }
set { resourceName = value; }
}
public List<string> ResourceStringList
{
get { return resourceStringList; }
set { resourceStringList = value; }
}
}
}
The xaml:
<Window x:Class="WpfApplication.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 x:Name="_dataGrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding KeyIndex}" Header="Key Index"/>
<DataGridTextColumn Binding="{Binding FileName}" Header="File Name"/>
<DataGridTextColumn Binding="{Binding ResourceName}" Header="Resource Name"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>