Click here to Skip to main content
15,885,835 members
Articles / Desktop Programming / WPF

How to Bind 2D Array to Listview in WPF?

Rate me:
Please Sign up or sign in to vote.
4.71/5 (6 votes)
19 Mar 2010CPOL1 min read 47.3K   1K   10   4
2 solutions how to bind 2 array ListView in WPF
binding_2d_array_listview.png

Introduction

WPF binding is useful and powerful. You can bind anything to ItemsControl.ItemsSource which inherited from IEnumerable interface, like one dimension array, List<T>, Collection<T>, and so on. But it can bind a 2D array. An exception "Array was not a one-dimensional array" is shown if you bind a multi-dimension array, like 2D array. 

Solution 1: Convert to a Class which Inherited from IEnumerable Interface, like DataTable, then Bind it to ListView

Many classes are inherited from IEnumerable, like List<T>, Collection<T>, Dictionary<Key, Value> and so on. In this solution, I plan to convert it to DataTable for general use. 

Prepare a 2D array first, we generated a 2d array with 100000 * 6. 

C#
double[,] data = new double[100000, 6];
for (int i = 0; i < data.GetLength(0); i++)
{
    data[i, 0] = i + 1;
    for (int j = 1; j < data.GetLength(1); j++)
    {
        data[i, j] = j + 1;
    }
}

We convert this array to a DataTable, the columns count of DataTable should equal to the 2nd dimension length of array, in this sample, it was 6. 

C#
private DataTable Convert2DArrayToDataTable(double[,] data, string[] columnNames)
{
    int len1d = data.GetLength(0);
    int len2d = data.GetLength(1);
    Check2DArrayMatchColumnNames(data, columnNames);

    DataTable dt = new DataTable();
    for (int i = 0; i < len2d; i++)
    {
        dt.Columns.Add(columnNames[i], typeof(double));
    }

    for (int row = 0; row < len1d; row++)
    {
        DataRow dr = dt.NewRow();
        for (int col = 0; col < len2d; col++)
        {
            dr[col] = data[row, col];
        }
        dt.Rows.Add(dr);
    }

    return dt;
}

private void Check2DArrayMatchColumnNames(double[,] data, string[] columnNames)
{
    int len2d = data.GetLength(1);

    if (len2d != columnNames.Length)
    {
        throw new Exception("The second dimensional length must equals column names.");
    }
}

What are the columnNames? We used it as field names in DataTable. It's useful when you are debugging, you can view the DataTable in DataView. Next, we initialized the ListView view and columns. 

C#
private void Binding2DArrayToListView
	(ListView listview, double[,] data, string[] columnNames)
{
    Check2DArrayMatchColumnNames(data, columnNames);

    DataTable dt = Convert2DArrayToDataTable(data, columnNames);

    GridView gv = new GridView();
    for (int i = 0; i < data.GetLength(1); i++)
    {
        GridViewColumn col = new GridViewColumn();
        col.Header = columnNames[i];
        col.DisplayMemberBinding = new Binding("[" + i + "]");
        gv.Columns.Add(col);
    }

    lvwArray.View = gv;
    lvwArray.ItemsSource = dt.Rows;
}

Now, it's done. But this kind of solution which needs conversion has a performance issue. Conversion will take a long time if the array is a larger one. Whatever converts to any type. What's the better solution? Please continue to solution 2.

Solution 2: Write an Array Visitor, then Bind it to ListView

The most difference between solution 1 and solution 2 are, the solution needs a process conversion. But solution 2 does not need it. We write an array visitor to visit array. Here comes the code:

C#
class ArrayVisitor : IEnumerable<double[]>
{
    private double[,] _data;

    public ArrayVisitor()
    {
    }

    public ArrayVisitor(double[,] data)
    {
        _data = data;
    }

    public double[,] Data
    {
        get { return _data; }
        set { _data = value; }
    }

    #region IEnumerable<double[]> Members

    public IEnumerator<double[]> GetEnumerator()
    {
        if (_data == null)
            throw new ArgumentException("Data cannot be null.", "Data");

        int len2d = _data.GetLength(1);

        for (int i = 0; i < _data.GetLength(0); i++)
        {
            double[] arr = new double[len2d];
            for (int j = 0; j < len2d; j++)
            {
                arr[j] = _data[i, j];
            }

            yield return arr;
        }
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    #endregion
}

How to use it in code?

C#
private void Bindng2DArrayToListview2
	(ListView listview, double[,] data, string[] columnNames)
{
    Check2DArrayMatchColumnNames(data, columnNames);

    GridView gv = new GridView();
    for (int i = 0; i < data.GetLength(1); i++)
    {
        GridViewColumn col = new GridViewColumn();
        col.Header = columnNames[i];
        col.DisplayMemberBinding = new Binding("[" + i + "]");
        gv.Columns.Add(col);
    }

    ArrayVisitor arrayVisitor = new ArrayVisitor(data);
    listview.View = gv;
    listview.ItemsSource = arrayVisitor;
}

Enjoy the code!

History

  • 19th March, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
China China
I started to programming in 2002, started when I was grade 2 in university, I participated some part-time projects at that time, I have much experiences on Windows, includes C#, ASP.NET, Visual Basic, Visual C++, AJAX, Power Shell Script, JavaScript, XML..etc, I am learning design and architect.

Comments and Discussions

 
GeneralMy vote of 5 Pin
marks johnson30-Aug-12 15:41
marks johnson30-Aug-12 15:41 
Questiondifferent background for each cell Pin
Member 87783552-Apr-12 5:07
Member 87783552-Apr-12 5:07 
AnswerRe: different background for each cell Pin
CooperWu4-Apr-12 2:36
CooperWu4-Apr-12 2:36 
GeneralAwesome....... Pin
hadai13-Jan-11 15:32
hadai13-Jan-11 15:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.