Como exibir imagens em dataGridView?

Oct 27 2020

Descrição.
Supõe-se para armazenar os caminhos para imagens como *.ico, *.jpg, *.pngno banco de dados.
Tipos de banco de dados:

  • SQLlite;
  • Servidor SQL;
  • MySQL;

Estou usando DataTable dtpara simular o resultado de uma SELECTconsulta.

Questão.

  1. Como exibir imagens em dataGridView?
  2. Qual é a prática mais comum para armazenar imagens em um banco de dados? Armazenar como caminhos ou é melhor usar outras opções?
  3. Existem erros no código?

Estou executando o aplicativo.
Resultado: erro.
Erro:
exceção em DataGridView:
System.FormatException : conversão inválida "System.String" para "System.Drawing.Image".

Imagem 1

Código

public partial class Form1 : Form
{
    DataTable dt = new DataTable();
    string pathProject = AppDomain.CurrentDomain.BaseDirectory;

    public Form1()
    {
        InitializeComponent();

        dgv.CellFormatting += Dgv_CellFormatting;
    }

    private void Dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        if (dgv.Columns[e.ColumnIndex].Name == "IcoPath")
        {
            string fullpath = pathProject + e.Value.ToString();

            // e.Value = Bitmap.FromFile(fullpath);

            Image p_ImageIn = new Bitmap(fullpath);
            ImageConverter imgConverter = new ImageConverter();
            e.Value = (byte[])imgConverter.ConvertTo(p_ImageIn, typeof(Byte[]));
            e.FormattingApplied = true;
        }

    }

    private void button1_Click(object sender, EventArgs e)
    {
        dt.Columns.Add("Name", typeof(string));
        dt.Columns.Add("IcoPath", typeof(string));
        dt.Columns.Add("JpgPath", typeof(string));
        dt.Columns.Add("PngPath", typeof(string));


        // dt.Rows.Add("Name_1", @"Resources\Picture\ico\ico_1.ico");
        // dt.Rows.Add("Name_2", @"Resources\Picture\ico\ico_2.ico");
        // dt.Rows.Add("Name_3", @"Resources\Picture\ico\ico_3.ico");

        // dt.Rows.Add("Name_1", @"Resources\Picture\jpg\Jpg_1.jpg");
        // dt.Rows.Add("Name_2", @"Resources\Picture\jpg\Jpg_2.jpg");
        // dt.Rows.Add("Name_3", @"Resources\Picture\jpg\Jpg_3.jpg");

        // dt.Rows.Add("Name_1", @"\Resources\Picture\png\Png_1.png");
        // dt.Rows.Add("Name_2", @"\Resources\Picture\png\Png_2.png");
        // dt.Rows.Add("Name_3", @"\Resources\Picture\png\Png_3.png");

        dt.Rows.Add("Name_1", @"Resources\Picture\ico\ico_1.ico", @"Resources\Picture\jpg\Jpg_1.jpg", @"\Resources\Picture\png\Png_1.png");
        dt.Rows.Add("Name_2", @"Resources\Picture\ico\ico_2.ico", @"Resources\Picture\jpg\Jpg_2.jpg", @"\Resources\Picture\png\Png_2.png");
        dt.Rows.Add("Name_3", @"Resources\Picture\ico\ico_3.ico", @"Resources\Picture\jpg\Jpg_3.jpg", @"\Resources\Picture\png\Png_3.png");

        DataGridViewImageColumn icoColumn = new DataGridViewImageColumn();
        //icoColumn.HeaderText = "Image_Header";
        icoColumn.Name = "IcoPath_Name";
        icoColumn.DataPropertyName = "IcoPath";
        //// dgv.Columns.Insert(3, imageColumn);
        dgv.Columns.Add(icoColumn);

        DataGridViewImageColumn jpgColumn = new DataGridViewImageColumn();
        //icoColumn.HeaderText = "Image_Header";
        jpgColumn.Name = "JpgPath_Name";
        jpgColumn.DataPropertyName = "JpgPath";
        //// dgv.Columns.Insert(3, imageColumn);
        dgv.Columns.Add(jpgColumn);


        DataGridViewImageColumn pngColumn = new DataGridViewImageColumn();
        //icoColumn.HeaderText = "Image_Header";
        pngColumn.Name = "PngPath_Name";
        pngColumn.DataPropertyName = "PngPath";
        //// dgv.Columns.Insert(3, imageColumn);
        dgv.Columns.Add(pngColumn);


        dgv.DataSource = dt;
    }
}

Imagem 2


Update-1

Ao criar uma solução para este problema, não considere as imagens como "incorporadas ao projeto".
Lógica do aplicativo:

  • conectar-se ao banco de dados;
  • execute a solicitação;
  • consulta resultar: DataTable dt;
  • DataTable dt contém caminhos para imagens;

Respostas

2 JohnG Oct 27 2020 at 23:17

Basicamente, como as imagens NÃO vêm de um banco de dados, mas são incorporadas ao projeto, conforme mostrado na imagem do explorador de soluções, seu código terá que “construir” isso DataTableusando esses recursos incorporados.

Parece que o que você está tentando fazer é “adicionar” as imagens à “coluna” das grades. Você deseja adicionar as imagens às DataTableLINHAS. Então, será desnecessário “adicionar” a coluna “imagem da grade” à grade. A grade saberá como exibir as imagens do, uma DataTablevez que são imagens “reais”.

Abaixo está um pequeno exemplo com apenas uma coluna de imagem, no entanto, não deve ser difícil adicionar as outras colunas usando a mesma estratégia. Além disso, estou recebendo as imagens que estão incorporadas como um recurso no projeto, conforme mostra sua imagem atual. Você precisará alterar o texto que diz “ProjectName” com o nome do seu projeto, além dos nomes dos arquivos de imagem.

  DataTable dt = new DataTable();
  dt.Columns.Add("Name", typeof(string));
  dt.Columns.Add("JpgPath", typeof(Image));

  Assembly myAssembly = Assembly.GetExecutingAssembly();
  Stream myStream = myAssembly.GetManifestResourceStream("ProjectName.Resources.Picture.jpg.image1.jpg");
  Image jpg1 = new Bitmap(myStream);
  myStream = myAssembly.GetManifestResourceStream("ProjectName.Resources.Picture.jpg.image2.jpg");
  Image jpg2 = new Bitmap(myStream);
  myStream = myAssembly.GetManifestResourceStream("ProjectName.Resources.Picture.jpg.image3.jpg");
  Image jpg3 = new Bitmap(myStream);

  dt.Rows.Add("Name1", jpg1);
  dt.Rows.Add("Name2", jpg2);
  dt.Rows.Add("Name3", jpg3);

  dgv.DataSource = dt;

Edite a partir da pergunta do OP.

O exemplo abaixo mostra dois métodos. O primeiro é uma simulação de obtenção dos dados do banco de dados onde as imagens não estão lá, mas os caminhos de string para as imagens estão.

Assim que tivermos o DataTabledo banco de dados, precisamos “adicionar” essas imagens a cada linha do existente DataTable. Obviamente, precisamos “adicionar” a nova coluna “Imagem” à existente DataTableque obtivemos do banco de dados. Em seguida, faça um loop em cada linha e adicione a imagem à coluna da imagem com base no caminho dessa linha.

private void Form1_Load(object sender, EventArgs e) {
  DataTable DBTable = GetTableFromDB();
  AddImageColumnToDT(DBTable);
  dgv.DataSource = DBTable;
}


private DataTable GetTableFromDB() {
  DataTable dt = new DataTable();
  dt.Columns.Add("Name", typeof(string));
  dt.Columns.Add("ImagePath", typeof(string));
  dt.Rows.Add("Name1", "PathTo_Image1");
  dt.Rows.Add("Name2", "PathTo_Image2");
  dt.Rows.Add("Name3", "PathTo_Image3");
  return dt;
}

private void AddImageColumnToDT(DataTable dt) {
  dt.Columns.Add("Image", typeof(Image));
  string curPath;
  Image curImage;
  foreach (DataRow row in dt.Rows) {
    curPath = row["ImagePath"].ToString();
    curImage = Image.FromFile(curPath);
    row["Image"] = curImage;
  }
}

EDIT *** se o banco de dados retornar uma byte[]coluna de array "vazia" em vez de um Imagetipo.

private DataTable GetTableFromDB2() {
  DataTable dt = new DataTable();
  dt.Columns.Add("Name", typeof(string));
  dt.Columns.Add("ImagePath", typeof(string));
  dt.Columns.Add("Image", typeof(byte[]));
  dt.Rows.Add("Name1", "PathTo_Image1");
  dt.Rows.Add("Name2", "PathTo_Image2");
  dt.Rows.Add("Name3", "PathTo_Image3");
  return dt;
}

private void AddImageColumnToDT2(DataTable dt) {
  //dt.Columns.Add("Image", typeof(byte[]));
  string curPath;
  Image curImage;
  byte[] curByteArray;
  foreach (DataRow row in dt.Rows) {
    curPath = row["ImagePath"].ToString();
    curImage = Image.FromFile(curPath);
    curByteArray = imageToByteArray(curImage);
    row["Image"] = curByteArray;
  }
}

public byte[] imageToByteArray(Image imageIn) {
  using (MemoryStream ms = new MemoryStream()) {
    imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
    return ms.ToArray();
  }
}