0

I am working with a requirement for displaying a 2 dimensional array in a WPF window. The size of array can be up to 360*720. I have tried to use DataTable bound to a DataDrid, but it took so much time to load the grid and very RAM consuming. My example code is below.

public void SetData(double[][] array)
{   
    if(array.Length <= 0)
        return;
    DataTable table = new DataTable();
    for (int i = 0; i < array[0].Length; i++)
    {
        table.Columns.Add(i.ToString(), typeof(double));
    }
    for (int i = 0; i < array.Length; i++)
    {
        DataRow row = table.NewRow();
        for (int j = 0; j < array[i].Length; j++)
        {
            row[j] = array[i][j].ToString();
        }
        table.Rows.Add(row);
    }
    dataGrid.DataContext = table;
}

I created an array of double of which the dimension is 360 * 720 and called the SetData() method above. As a result, the RAM occupied by the program increased several GBs and very time consuming.

I wonder if there is a graceful way to solve this problem or there are some shortcomings in my code. Thank you.

Dream Land
  • 31
  • 5
  • DataGrids don't have to bind to DataTables, unless its 2002, you can use Object Lists, have you tried a one liner `dataGrid.DataContext = array;;`? Also no need to cast to string `array[i][j].ToString()` – Jeremy Thompson Jan 21 '22 at 03:39
  • I could be mistaken, however, what your code shows and what your comments say are two different things. The code… `double[][] array` … is NOT necessarily a 2-dimensional array which is what you claim in your comments. This is a jagged array of arrays which is different than a true 2-dimensional array which would be defined as `double[,]`. You may find the following two questions useful… – JohnG Jan 21 '22 at 03:50
  • [What are the differences between a multidimensional array and an array of arrays in C#?](https://stackoverflow.com/questions/597720/what-are-the-differences-between-a-multidimensional-array-and-an-array-of-arrays) … And … [Multidimensional Array](https://stackoverflow.com/questions/12567329/multidimensional-array-vs) – JohnG Jan 21 '22 at 03:51
  • I am just saying that a true 2-dimensional 360*720 array is NOT a lot of data especially if they are only double values and should take less than second to load. – JohnG Jan 21 '22 at 03:57
  • Take a look at Virtual List Views. They can handle millions of rows quite efficiently. https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.listview.virtualmode?view=windowsdesktop-6.0. It’s important that both the underlying data and UI elements that make up the grid are **virtualised** –  Jan 21 '22 at 03:59
  • Really really thank you all for the useful answers and comments! – Dream Land Jan 21 '22 at 05:48
  • @JeremyThompson, one liner `dataGrid.DataContext = array;` won't do any good. Binding is more complicated than that. DataTable has *many* useful features (built-in filtering!) and still a viable choice in year 2022. – ASh Jan 21 '22 at 08:01

2 Answers2

0

Thanks for all these useful answers and comments which helped me a lot. After doing some search, I seemed to find out the reason why my code costs so much time to render the DataGrid. I wrapped up the grid with a ScrollViewer before. I removed it and it went very well. Here is the link where I found the tip.WPF DataGrid is very slow to render.

Thank you all.

Dream Land
  • 31
  • 5
-1

Create a separate class that can return the enumerator as data.

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
}

You can use Listview and Gridview as Databound controls.
  
   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;
    }
  • Thank you so much! It really works! I learn a lot from your code. I need some time to understand what the difference is behind the code. Thank you! – Dream Land Jan 21 '22 at 03:56
  • Pleasure! And Don't miss to UpVote answer if it helped you to any extent. Thank You. Happy Coding! – Sumit Sharma Jan 21 '22 at 04:47