I need to build and display a WPF data grid from a collection of string array that i got from a txt. The problem is that i don't know a priori which will be the number of columns i.e. the number of item in the single array. So i defined in my xaml <DataGrid Grid.Row="2" ItemsSource="{Binding Path=Rows}" />
I was trying to fill it in my View Model, but i cannot simply put my collection (Observable Collection) of array as item source, since the datagrid will display only blank rows.
I can also use other approach over the Observable collection since i produce my array in the same method
this is my Observable Collection:
ObservableCollection<string[]> Rows = new ObservableCollection<string[]>;
in this method i fill the collection
foreach(ListViewItem item in wsettings.lista)
{
TextBlock line = item.Content as TextBlock;
string txt = line.Text;
string[] x = txt.Split(stringSeparators, StringSplitOptions.None);
Rows.Add(x);
}
Please don't mind the first part before the split. I take my data from a listview of text block that i used before(I have my reason).
EDIT1: made the code more readable
EDIT2: the header must be a combobox that a user must set
There is DataTable
class in .Net. Its primary purpose is to communicate with relational database but it can be used nicely to store, display and edit tabular data (e.g. read and display .csv/Excel files -> DataTable + DataGrid
in wpf, DataTable + DataGridView
in WinForms).
DataTable columns (DataColumn) can be added/removed at runtime and DataGrid auto-generates columns (DataGridColumn) for them (enabled by default), using Name property for headers. Also DataTable supports sorting and filtering out-of-box.
note: DataGrid doesn't clear Columns
when new ItemsSource is assigned. So it is possible to have some predefined columns and use autogenerate as well.
note: DataGrid creates DataGridTextColumn
s by default. If more complex template is required, the process can be intercepted via AutoGeneratingColumn
event (see example)
here is an example:
code
public class MyViewModel
{
public DataTable Test { get; set; }
}
public MyWindow()
{
InitializeComponent();
var vm = new MyViewModel
{
Test = new DataTable
{
Columns = {"A", "B", "C"}
}
};
this.DataContext = vm;
}
xaml
<DataGrid AutoGenerateColumns="True"
ItemsSource="{Binding Path=Test.DefaultView}">
<DataGrid.Columns>
<DataGridTextColumn Header="#"/>
</DataGrid.Columns>
</DataGrid>
the result (I entered some values)
If you don't know the number of columns at compile-time, you need to create the columns programmatically. This should be pretty straight-forward to do in the view. The following sample code should give you the idea:
public MainWindow()
{
InitializeComponent();
var viewModel = new ViewModel();
var rows = viewModel.Rows;
int numberOfColumns = rows[0].Length; //assume all string[] have the same length
DataContext = new VM1();
for (int i = 0; i < numberOfColumns; ++i)
{
dataGrid1.Columns.Add(new DataGridTextColumn() { Binding = new Binding("[" + i + "]"), Header = i.ToString() });
}
dataGrid1.ItemsSource = rows;
}