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.
CodePudding user response:
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.
CodePudding user response:
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;
}
