c# DataGridView to Bitmap
Всем привет. Нужно конвертировать таблицу в картинку. Самый очевидный, как по мне способ - каждую отдельную строку "сфотографировать", сохранить в лист и затем соединять в одну большую картинку. Написал вот такой код:
List<byte[]> rowList = new List<byte[]>(); //здесь сохраняем все строки
for (int i = 0; i < OrderDataGrid.Rows.Count; i++) //вот тут всё идеально работает и прекрасно сохраняется
//(исключение - если таблица не влезает вся в экран, вылазит исключение. Пока что, не знаю, как с этим разобраться)
{
OrderDataGrid.Rows[i].Selected = true;
Size dgvSz = OrderDataGrid.ClientSize;
int rw = OrderDataGrid.Rows[i].Index;
Rectangle RowRect = OrderDataGrid.GetRowDisplayRectangle(rw, true);
using (Bitmap bmpDgv = new Bitmap(dgvSz.Width, dgvSz.Height))
using (Bitmap bmpRow = new Bitmap(RowRect.Width, RowRect.Height))
{
OrderDataGrid.DrawToBitmap(bmpDgv, new Rectangle(Point.Empty, dgvSz));
using (Graphics G = Graphics.FromImage(bmpRow))
{
G.DrawImage(bmpDgv, new Rectangle(Point.Empty, RowRect.Size), RowRect, GraphicsUnit.Pixel);
string DesktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
using (MemoryStream stream = new MemoryStream())
{
bmpRow.Save(stream, ImageFormat.Bmp);
rowList.Add(stream.ToArray());
}
}
}
}
int TotalHeight = (OrderDataGrid.RowCount * OrderDataGrid.RowTemplate.Height) +
OrderDataGrid.ColumnHeadersHeight;
Bitmap result = new Bitmap(OrderDataGrid.ClientSize.Width, TotalHeight);
result.SetResolution(100, 100);
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Graphics g = Graphics.FromImage(result);
int btmCount = 0; //счётчик bitmap
for (int y = 0; y < TotalHeight - OrderDataGrid.RowTemplate.Height; y += OrderDataGrid.RowTemplate.Height)
{//вот тут происходит какая-то странная магия и всё ломается. Не могу понять, в чём дело
//Он выдаёт мне результат, но это просто 6 пустых строк
using (Bitmap tempBitmap = (Bitmap)tc.ConvertFrom(rowList[btmCount]))
{
for (int x = 0; x < OrderDataGrid.ClientSize.Width; x += 1)
{
g.DrawImage(tempBitmap, x, y);
}
}
btmCount++;
}
string DesktopFolder2 = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
result.Save(Path.Combine(DesktopFolder2 + @"\Folder\", "datagridview.png"), ImageFormat.Png);
result:
Ответы (3 шт):
Найдено в гугле по первой ссылке по... заголовку этого вопроса
//Изменить высоту к оригинальной
int height = dataGridView1.Height;
dataGridView1.Height = dataGridView1.RowCount * dataGridView1.RowTemplate.Height;
//Создать битмап и врисовать туда DataGridView
Bitmap bitmap = new Bitmap(this.dataGridView1.Width, this.dataGridView1.Height);
dataGridView1.DrawToBitmap(bitmap, new Rectangle(0, 0, this.dataGridView1.Width, this.dataGridView1.Height));
//Изменить DataGridView назад к оригинальному размеру
dataGridView1.Height = height;
//Сохранить в папку
bitmap.Save(@"D:\Images\DataGridView.png");
Рабочий способ. Работает не очень быстро и немного дёргано, но работает. Если подскажите, как его можно оптимизировать, буду благодарен. (сделал "общим")
int TotalHeight = (OrderDataGrid.RowCount * OrderDataGrid.RowTemplate.Height) +
OrderDataGrid.ColumnHeadersHeight;
Bitmap result = new Bitmap(OrderDataGrid.ClientSize.Width, TotalHeight);
Graphics g = Graphics.FromImage(result);
result.SetResolution(100, 100);
int x = 0;
int y = 0;
for (int i = 0; i < OrderDataGrid.Rows.Count; i++)
{
OrderDataGrid.Rows[i].Selected = true;
Size dgvSz = OrderDataGrid.ClientSize;
int rw = OrderDataGrid.Rows[i].Index;
Rectangle RowRect = OrderDataGrid.GetRowDisplayRectangle(rw, true);
using (Bitmap bmpDgv = new Bitmap(dgvSz.Width, dgvSz.Height))
using (Bitmap bmpRow = new Bitmap(RowRect.Width, RowRect.Height))
{
OrderDataGrid.DrawToBitmap(bmpDgv, new Rectangle(Point.Empty, dgvSz));
using (Graphics G = Graphics.FromImage(bmpRow))
{
G.DrawImage(bmpDgv, new Rectangle(Point.Empty, RowRect.Size), RowRect, GraphicsUnit.Pixel);
g.DrawImage(bmpRow, x, y);
}
}
y += OrderDataGrid.RowTemplate.Height;
try
{ OrderDataGrid.FirstDisplayedScrollingRowIndex++; }
catch { }
}
string DesktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
result.Save(Path.Combine(DesktopFolder, "datagridview.png"), ImageFormat.Png);
Вероятно, это самый простой способ отрисовать весь DataGridView в Bitmap:
using (var form = new Form())
using (var dgv = new DataGridView())
{
dgv.Parent = form;
dgv.AutoSize = true;
dgv.DataSource = source;
using (var bitmap = new Bitmap(dgv.Width, dgv.Height))
{
dgv.DrawToBitmap(bitmap, dgv.Bounds);
bitmap.Save("datagridview.png", ImageFormat.Png);
}
}
Если задать свойство AutoSize = true;, то грид увеличится (или уменьшится) так, чтобы вместить все строки. После чего вызов DrawToBitmap даст желаемый результат.
Т. к. нежелательно, чтобы реальный контрол менял размеры на реальной форме (это может привести к пересчёту всего Layout), создаём временную форму и грид.
source - это источник данных (коллекция), к которому делаем привязку. Если у вас не используется Data binding, то нужно у временного грида создать такие же колонки, как у реального и скопировать в него строки.
Что интересно, эту временную форму не обязательно показывать вызовом Show() или ShowDialog(), а гриду обязательно нужно иметь родителя.
