3

I'm trying to get a DataGrid to display the contents of an object[][]. This'll be read-only so I don't care about notification changes or anything like that. Setting ItemSource to an object[][] simply displays the properties of Array in the grid, and using List<List<object>> instead does the same, which is decidedly unhelpful.

The number of columns in each 1d array can be arbitary; I simply want an unnamed column to be created for each array element in each row. How can I do this?

1
  • 1
    5 points from 10K, congrats :) Commented Dec 16, 2010 at 13:51

1 Answer 1

1

See my answer in this question. This will also enable editing of the values. Since you're just interested in displaying them it might be easier to use the answer from Jobi Joy if using the DataGrid isn't a requirement.

To make a short version of the answer from that question. You'll need a Ref class

public class Ref<T>
{  
    private readonly Func<T> getter;   
    private readonly Action<T> setter;  
    public Ref(Func<T> getter, Action<T> setter)   
    {   
        this.getter = getter;   
        this.setter = setter;   
    }  
    public T Value { get { return getter(); } set { setter(value); } }   
}  

And a helper class to get dynamic columns from the 2d array

public class BindingHelper
{
    public DataView GetBindable2DViewFromIList<T>(IList list2d)
    {
        DataTable dataTable = new DataTable();
        for (int i = 0; i < ((IList)list2d[0]).Count; i++)
        {
            dataTable.Columns.Add(i.ToString(), typeof(Ref<T>));
        }
        for (int i = 0; i < list2d.Count; i++)
        {
            DataRow dataRow = dataTable.NewRow();
            dataTable.Rows.Add(dataRow);
        }
        DataView dataView = new DataView(dataTable);
        for (int i = 0; i < list2d.Count; i++)
        {
            for (int j = 0; j < ((IList)list2d[i]).Count; j++)
            {
                int a = i;
                int b = j;
                Ref<T> refT = new Ref<T>(() => (list2d[a] as IList<T>)[b], z => { (list2d[a] as IList<T>)[b] = z; });                    
                dataView[i][j] = refT;
            }
        }
        return dataView;
    }
}

After that you can use ItemsSource like this

<DataGrid Name="dataGrid" 
          RowHeaderWidth="0" 
          ColumnHeaderHeight="0" 
          AutoGenerateColumns="True" 
          AutoGeneratingColumn="dataGrid_AutoGeneratingColumn"/> 

dataGrid.ItemsSource = BindingHelper.GetBindable2DViewFromIList<object>(m_2DArray);

private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) 
{ 
    DataGridTextColumn column = e.Column as DataGridTextColumn; 
    Binding binding = column.Binding as Binding; 
    binding.Path = new PropertyPath(binding.Path.Path + ".Value");
}
Sign up to request clarification or add additional context in comments.

1 Comment

I ended up just creating rows in the DataTable using Rows.Add(rowArray), and getting a DataView using AsDataView extension method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.