1

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

Daniele Sartori
  • 1,674
  • 22
  • 38
  • You shouldn't be doing these strange things with TextBlocks. You should just bind ItemsSource to an ObservableCollection in your viewmodel, just the way you tried to do. If you show us all the code you had when you tried to do it that way, we can help you get it right. – 15ee8f99-57ff-4f92-890c-b56153 May 26 '17 at 13:26
  • What column headers do you expect ? – Tarboeuf May 26 '17 at 13:28
  • @Daniele, you can use `DataTable` to store values and display it in a DataGrid – ASh May 26 '17 at 14:34
  • @ASh can you explain how? I've created a DataTable, and filled with my data. I modified my xamul as followinf : but still my datagrid is empty. Test is my DataTable. I even tried to save my datatable as DataView but no results – Daniele Sartori May 26 '17 at 15:01
  • @DanieleSartori, `AutoGenerateColumns` should be `True` and `ItemsSource` requires IEnumerable (dataTable.DefaultView, `ItemsSource="{Binding Path=DefaultView}" `). – ASh May 26 '17 at 15:12
  • @ASh you are my saviour. If you want to write an answer i'll mark yours. It work as i want – Daniele Sartori May 26 '17 at 15:25

2 Answers2

1

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 DataGridTextColumns 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)

datagrid

ASh
  • 34,632
  • 9
  • 60
  • 82
0

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;
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • That would be surely a solution. I just would have liked to do it in View Model – Daniele Sartori May 26 '17 at 13:40
  • The view model shouldn't be responsible for creating DataGrid columns. This would break the MVVM pattern. This is view based functionality that belongs to the view. The VM simply exposes a collection for the view to bind to. – mm8 May 26 '17 at 13:41
  • @mm8 how do you relate the collection with the binding this way? – G.Anıl Yalçın Jul 06 '17 at 20:38