Я создал несколько вспомогательных классов, чтобы использовать DataGrid как своего рода DataTable. Другими словами, я хотел форматировать, сортировать и полировать внешний вид DataGrid без необходимости предварительно создавать некоторые классы заранее. Основная причина, по которой я хотел это, была для набора тестов, я хотел иметь возможность создавать произвольное количество столбцов и во время выполнения. Вот что я получил
public class DataRow
{
internal List<object> Items = new List<object>();
public object this[string value]
{
get { return Items[Convert.ToInt32(value)]; }
}
public string GetString(int index)
{
return Items[index].ToString();
}
public object GetObject(int index)
{
return Items[index];
}
public DataRow(params object[] values)
{
if (values == null || values.Length < 1)
throw new Exception("You must pass in some values");
Items.AddRange(values);
}
}
public class GridConstructor
{
public List<DataRow> Rows = new List<DataRow>();
private DataRow headers;
public GridConstructor(DataRow head)
{
headers = head;
}
public void BuildInto(DataGrid grid)
{
grid.AutoGenerateColumns = false;
grid.Columns.Clear();
int totalCols = 0;
Type headType = headers.GetType();
for (int i = 0; i < headers.Items.Count; i++)
{
grid.Columns.Add(GetCol(headers.GetString(i), String.Concat("[", i.ToString(),"]")));
totalCols++;
}
int finalWidth = totalCols * (int)grid.ColumnWidth.Value + 15;
grid.Width = finalWidth;
grid.ItemsSource = Rows;
}
private DataGridTextColumn GetCol(string header, string binding)
{
DataGridTextColumn col = new DataGridTextColumn();
col.IsReadOnly = true;
col.Header = header;
col.Binding = new Binding(binding);
return col;
}
public DataGrid Create(int colSize)
{
DataGrid grid = new DataGrid();
grid.ColumnWidth = colSize;
grid.CanUserAddRows = false;
grid.AlternationCount = 2;
BuildInto(grid);
return grid;
}
}
Соединяя это, это пример использования:
void SimpleTest_Loaded(object sender, RoutedEventArgs e)
{
DataRow headers = new DataRow("Level", "Weapon Type", "vs None", "vs Leather", "vs Studded", "vs Brigandine");
GridConstructor gridConstructor = new GridConstructor(headers);
var weaponType = "Slash";
for (int level = 1; level < 10; level++)
{
int damage = DiceCup.RollMulti(8, level);
int damCloth = damage - DiceCup.RollMulti(2, level);
int damLeather = damage - DiceCup.RollMulti(3, level);
int damStudded = damage - DiceCup.RollMulti(4, level);
int damBrigandine = damage - DiceCup.RollMulti(5, level);
DataRow row = new DataRow(level, weaponType, damage, damCloth, damLeather, damStudded, damBrigandine);
gridConstructor.Rows.Add(row);
}
//Create the grid.
var grid = gridConstructor.Create(100);
//Create a chart.
Chart chart = new Chart();
chart.Height = 200;
chart.LegendTitle = "Legend";
chart.Title = "Slash vs Armor Types";
chart.DataContext = gridConstructor.Rows;
//Create our series, or lines.
LineSeries slashVsNone = new LineSeries();
slashVsNone.Title = "vs None";
slashVsNone.DependentValueBinding = new Binding("[2]");
slashVsNone.IndependentValueBinding = new Binding("[0]");
slashVsNone.ItemsSource = gridConstructor.Rows;
chart.Series.Add(slashVsNone);
//Presentation is a stackpanel on the page.
presentation.Children.Add(grid);
presentation.Children.Add(chart);
}
И вывод:
альтернативный текст http://quiteabnormal.com/images/codeSample.jpg
Обратите внимание, что раскраска сетки происходит от универсальных стилей, установленных на странице. Если вы используете метод GridConstructor.BuildInto (), вы можете указать сетку, которую вы предварительно отформатировали, в Blend или что-то подобное.
Только одна вещь, GridConstructor делает некоторые предположения о начальных настройках столбца. Вы можете изменить класс, чтобы сделать его более настраиваемым, если хотите, но это то, что мне было нужно, поэтому я хотел иметь возможность сделать это без суеты.