在C#中从List <List >显示DataGridView中的HeatMap

我已经在列表列表中得到了一些数据。 我的任务是制作热图。 作为C#的新手,我搜索网络并找到了一种通过在DataGridView中绘制元素来解决此任务的方法,但我不明白,该怎么做。 所以,我有一个Touples列表:

using SpikeDataPacket = List<Tuple>; 

这是我在网格中加载数据的方式:

 public HeatForm(List list) { SpikeList = list; InitializeComponent(); var bindstim = new BindingList(SpikeList); var stimsource = new BindingSource(bindstim, null); heatMap.DataSource = stimsource; } 

但是这会在DataGridView中显示一个“capacity”和“count”的表,但不显示数据。 另外,我已经找到了计算颜色的方法,但不知道,如何应用它:

 private Color HeatMapColor(double value, double min, double max) { Color firstColour = Color.RoyalBlue; Color secondColour = Color.LightSkyBlue; // Example: Take the RGB //135-206-250 // Light Sky Blue // 65-105-225 // Royal Blue // 70-101-25 // Delta int rOffset = Math.Max(firstColour.R, secondColour.R); int gOffset = Math.Max(firstColour.G, secondColour.G); int bOffset = Math.Max(firstColour.B, secondColour.B); int deltaR = Math.Abs(firstColour.R - secondColour.R); int deltaG = Math.Abs(firstColour.G - secondColour.G); int deltaB = Math.Abs(firstColour.B - secondColour.B); double val = (value - min) / (max - min); int r = rOffset - Convert.ToByte(deltaR * (1 - val)); int g = gOffset - Convert.ToByte(deltaG * (1 - val)); int b = bOffset - Convert.ToByte(deltaB * (1 - val)); return Color.FromArgb(255, r, g, b); } 

先感谢您!

我想我会以不同的方式解决这个问题。

  • 我会在使用DataBinding 情况下开始。 列表结构列表列表和双精度到Color的映射都不适合DataBinding
  • 我也不确定你的颜色映射算法..

要将数据填充到DataGridView DGV中,我使用一个简单的例程,它首先准备DGV,然后绘制单元格:

 void fillData() { int maxRow = data.Count; int maxCol = data[0].Count; double factor = 1.0; DGV.RowHeadersVisible = false; DGV.ColumnHeadersVisible = false; DGV.AllowUserToAddRows = false; DGV.AllowUserToOrderColumns = false; DGV.CellBorderStyle = DataGridViewCellBorderStyle.None; //.. int rowHeight = DGV.ClientSize.Height / maxRow - 1; int colWidth = DGV.ClientSize.Width / maxCol - 1; for (int c = 0; c < maxRow; c++) DGV.Columns.Add(c.ToString(), ""); for (int c = 0; c < maxRow; c++) DGV.Columns[c].Width = colWidth; DGV.Rows.Add(maxRow); for (int r = 0; r < maxRow; r++) DGV.Rows[r].Height = rowHeight; List baseColors = new List(); // create a color list baseColors.Add(Color.RoyalBlue); baseColors.Add(Color.LightSkyBlue); baseColors.Add(Color.LightGreen); baseColors.Add(Color.Yellow); baseColors.Add(Color.Orange); baseColors.Add(Color.Red); List colors = interpolateColors(baseColors, 1000); for (int r = 0; r < maxRow; r++) { for (int c = 0; c < maxRow; c++) { DGV[r,c].Style.BackColor = colors[ Convert.ToInt16( data[r][c].Item2 * factor)]; } } } 

您可能需要更改一些内容,尤其是基本颜色和要获取的颜色数,具体取决于您的值,还包括从double值到整数索引的映射!

这是创建插值颜色列表的function。 它需要一些基色和长度N并返回N个插值颜色。 这使得映射简单灵活。

 List interpolateColors(List stopColors, int count) { SortedDictionary gradient = new SortedDictionary(); for (int i = 0; i < stopColors.Count; i++) gradient.Add(1f * i / (stopColors.Count-1), stopColors[i]); List ColorList = new List(); using (Bitmap bmp = new Bitmap(count, 1)) using (Graphics G = Graphics.FromImage(bmp)) { Rectangle bmpCRect = new Rectangle(Point.Empty, bmp.Size); LinearGradientBrush br = new LinearGradientBrush (bmpCRect, Color.Empty, Color.Empty, 0, false); ColorBlend cb = new ColorBlend(); cb.Positions = new float[gradient.Count]; for (int i = 0; i < gradient.Count; i++) cb.Positions[i] = gradient.ElementAt(i).Key; cb.Colors = gradient.Values.ToArray(); br.InterpolationColors = cb; G.FillRectangle(br, bmpCRect); for (int i = 0; i < count; i++) ColorList.Add(bmp.GetPixel(i, 0)); br.Dispose(); } return ColorList; } 

我的测试数据是这样创建的:

 List>> data = new List>>(); Random R = new Random(); void createData(int maxRow, int maxCol) { for (int c = 0; c < maxRow; c++) { data.Add(new List>()); for (int r = 0; r < maxRow; r++) { data[c].Add(new Tuple(c, Math.Min(999, R.Next(r*c)))); } } } 

我用它是这样的:

 private void Form1_Load(object sender, EventArgs e) { createData(40, 40); fillData(); } 

这是一个(相当无聊)截图:

热图

根据需要获得显示后,您可能想要决定使用 DataBinding寻求解决方案。 我相信你需要使用OwnerDrawing the Cells 。 获得单元格中的值后,您可以使用相同的映射,如下所示:

 private void DGV_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { Color theColor = ..... e.Graphics.Clear(colors[theColor]); } 

这是一种颜色项目的简单方法:

在此处输入图像描述

我们的参考对象:

 internal class Item { public string Name { get; set; } public double Value { get; set; } } 

用法:

  • 粘贴代码并重新构建项目
  • 转到“数据源”窗格并创建新数据源
  • 选择该类型的对象,然后按“完成”
  • 将创建的源删除到from(它创建一个DataGridView

着色细胞:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // create some items itemBindingSource.Add(new Item {Name = "name1", Value = 0}); itemBindingSource.Add(new Item {Name = "name2", Value = 0.5}); itemBindingSource.Add(new Item {Name = "name3", Value = 1}); // find column index to color string columnName = "Value"; int columnIndex = -1; DataGridViewColumnCollection columns = itemDataGridView.Columns; for (int i = 0; i < columns.Count; i++) { DataGridViewColumn column = columns[i]; if (column.DataPropertyName == columnName) { columnIndex = i; break; } } // color cells if (columnIndex >= 0) { foreach (DataGridViewRow row in itemDataGridView.Rows) { if (!row.IsNewRow) { // get associated data var item = (Item) row.DataBoundItem; // build color from associated data Color fromArgb = Color.FromArgb((int) (item.Value*255), 128, 128); row.Cells[columnIndex].Style.BackColor = fromArgb; } } } } } 

然后卷起你自己的着色逻辑,