Вот элемент управления, называемый DataGrid2D
, который может быть заполнен на основе 2D или
1D массив (или все, что реализует интерфейс IList
). Он подклассов DataGrid
и добавляет свойство с именем ItemsSource2D
, которое используется для привязки к 2D или 1D источникам. Библиотеку можно скачать здесь , а исходный код можно загрузить здесь .
Чтобы использовать его, просто добавьте ссылку на DataGrid2DLibrary.dll, добавьте это пространство имен
xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary"
, а затем создайте DataGrid2D и привяжите его к вашему IList, 2D-массиву или 1D-массиву, как это
<dg2d:DataGrid2D Name="dataGrid2D"
ItemsSource2D="{Binding Int2DList}"/>
СТАРЫЙ ПОСТ
Вот реализация, которая может связать 2D-массив с сеткой данных WPF.
Скажем, у нас есть этот двумерный массив
private int[,] m_intArray = new int[5, 5];
...
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
m_intArray[i,j] = (i * 10 + j);
}
}
И затем мы хотим связать этот 2D-массив с WPF DataGrid, и сделанные нами изменения будут отражены в массиве. Для этого я использовал класс Ref Эрика Липперта из этого потока.
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); } }
}
Затем я создал статический вспомогательный класс с методом, который мог бы принимать 2D-массив и возвращать DataView, используя класс Ref выше.
public static DataView GetBindable2DArray<T>(T[,] array)
{
DataTable dataTable = new DataTable();
for (int i = 0; i < array.GetLength(1); i++)
{
dataTable.Columns.Add(i.ToString(), typeof(Ref<T>));
}
for (int i = 0; i < array.GetLength(0); i++)
{
DataRow dataRow = dataTable.NewRow();
dataTable.Rows.Add(dataRow);
}
DataView dataView = new DataView(dataTable);
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
int a = i;
int b = j;
Ref<T> refT = new Ref<T>(() => array[a, b], z => { array[a, b] = z; });
dataView[i][j] = refT;
}
}
return dataView;
}
Этого будет почти достаточно для привязки, но путь в привязке будет указывать на объект Ref, а не на Ref.Value, который нам нужен, поэтому мы должны изменить его, когда будут сгенерированы столбцы.
<DataGrid Name="c_dataGrid"
RowHeaderWidth="0"
ColumnHeaderHeight="0"
AutoGenerateColumns="True"
AutoGeneratingColumn="c_dataGrid_AutoGeneratingColumn"/>
private void c_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");
}
И после этого мы можем использовать
c_dataGrid.ItemsSource = BindingHelper.GetBindable2DArray<int>(m_intArray);
И вывод будет выглядеть так
Любые изменения, сделанные в DataGrid
, будут отражены в m_intArray.