zoukankan      html  css  js  c++  java
  • 关于在DataGridView中嵌入图片……

    有一句英语名言——Picutures speak louder than words(图片胜于千言万语)。可见在描述一些细节问题,或者是用语言文字难以让人产生“身临其境”的时候,图片就发挥了其作用。在WinForm中,DataGridView不仅仅是用于显示文字、我们还可以显示图片。本章就和大伙儿讨论DataGridView中嵌入显示图片的问题。

    一、嵌入式显示:

    所谓“嵌入式”,就是说把图片单独存放在某个DataTable的字段中(该字段为byte[]类型)然后绑定到对应DataGridView的指定单元格中显示出来,代码大致如下:

    [C#]

    public partial class Form1 : Form
    {
    DataGridView dgv = null;

    public Form1()
    {
    InitializeComponent();

    //初始化动态产生数据表等字段
    dgv = new DataGridView();
    dgv.Parent = this;
    dgv.Dock = DockStyle.Fill;

    DataTable dt = new DataTable();
    dt.Columns.Add("Name", typeof(string));
    dt.Columns.Add("Image", typeof(byte[]));
    dt.Rows.Add("Test1", File.ReadAllBytes("d:\\test.jpg"));
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
    dgv.DataSource = dt;
    }
    }

    [VB.NET]

    Public Partial Class Form1
    Inherits Form
    Private dgv As DataGridView = Nothing

    Public Sub New()
    InitializeComponent()

    '初始化动态产生数据表等字段
    dgv = New DataGridView()
    dgv.Parent = Me
    dgv.Dock = DockStyle.Fill

    Dim dt As New DataTable()
    dt.Columns.Add("Name", GetType(String))
    dt.Columns.Add("Image", GetType(Byte()))
    dt.Rows.Add("Test1", File.ReadAllBytes("d:\test.jpg"))
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
    dgv.DataSource = dt
    End Sub
    End Class

    这样做的好处在于:由于你的图片文件被嵌入到了数据库中(这里是模拟数据库的效果,真实情况下你应该使用DataAdapter.Fill填充到DataTable中方可)。这样不存在图片丢失等情况;当然数据库的容量也大大增加。

    二、连接式图片显示:

    这是我给起的名字,就是类似我“关于资源文件”中那个“Link when compile"效果差不多——只在动态绑定的时候根据一定规律(如存储在数据库中的绝对或者相对路径)顺序加载图片,这样图片和数据库必然是分离的。不过拷贝的时候注意路径等问题。示例代码如下:

    [C#]

    public partial class Form1 : Form
    {
    DataGridView dgv = null;

    public Form1()
    {
    InitializeComponent();

    //初始化动态产生数据表等字段
    dgv = new DataGridView();
    dgv.Parent = this;
    dgv.Dock = DockStyle.Fill;

    DataTable dt = new DataTable();
    dt.Columns.Add("Name", typeof(string));
    dt.Columns.Add("Image", typeof(string));
    dt.Rows.Add("Test1", "d:\\test.jpg");
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
    dgv.Columns.Add(new DataGridViewTextBoxColumn() { HeaderText = "Name", DataPropertyName = "Name" });
    dgv.Columns.Add(new DataGridViewImageColumn() { HeaderText = "Image", DataPropertyName = "Image" });
    dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);
    dgv.DataSource = dt;
    }

    void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
    if (e.ColumnIndex==1 && e.RowIndex!=dgv.NewRowIndex)
    {
    e.Value = File.ReadAllBytes(dgv.Rows[e.RowIndex].Cells[1].Value.ToString());
    }
    }
    }

    [VB.NET]

    Public Partial Class Form1
    Inherits Form
    Private dgv As DataGridView = Nothing

    Public Sub New()
    InitializeComponent()

    '初始化动态产生数据表等字段
    dgv = New DataGridView()
    dgv.Parent = Me
    dgv.Dock = DockStyle.Fill

    Dim dt As New DataTable()
    dt.Columns.Add("Name", GetType(String))
    dt.Columns.Add("Image", GetType(String))
    dt.Rows.Add("Test1", "d:\test.jpg")
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
    dgv.Columns.Add(New DataGridViewTextBoxColumn() With { _
    Key .HeaderText = "Name", _
    Key .DataPropertyName = "Name" _
    })
    dgv.Columns.Add(New DataGridViewImageColumn() With { _
    Key .HeaderText = "Image", _
    Key .DataPropertyName = "Image" _
    })
    AddHandler dgv.CellFormatting, AddressOf New DataGridViewCellFormattingEventHandler(AddressOf dgv_CellFormatting)
    dgv.DataSource = dt
    End Sub

    Private Sub dgv_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs)
    If e.ColumnIndex = 1 AndAlso e.RowIndex <> dgv.NewRowIndex Then
    e.Value = File.ReadAllBytes(dgv.Rows(e.RowIndex).Cells(1).Value.ToString())
    End If
    End Sub
    End Class

    以上代码和第一种”嵌入式“差不多,不过还请注意一下重要差别:

    1)自定义了各个Columns,而不是自动生成(这是因为DataTable中都是string类型,包括存储图片的路径,如果单用自动生成的话则无法生成Image类型的列)。

    2)人为使用了CellFormatting事件,该事件在呈现整个DataGridView的时候被出发。此时该事件的e的RowIndex将从0~最后一行(实际在DataTable中不存在),ColumnIndex从0~最后一列逐个遍历。如If中判断,其中e.ColumnIndex=1表示第一列,e.RowIndex不等于dgv.NewRowIndex表示不等于最后一行。同时给e.Value(实际单元格中内容)直接赋予其byte数组即可。

    附带说明一下:你把DataGridView的AllowUserToAddRows设置为False,那么“e.RowIndex <> dgv.NewRowIndex”完全可以省略。

    有兴趣的话,可以尝试结合我“关于资源文件”的方法,先把图片嵌入到资源文件中,然后在DataTable中某列添加各个对应资源文件的相对路径和名称,然后动态加载。

    三、图片大小调整:

    有时我们喜欢统一把图片“按比例缩放”,不喜欢很大或者很小的图片——怎么办?我们可以采取把图片的byte数组读入一个Memory中,然后加载到Image,同时创建新的BitMap(利用其构造函数定义统一的Size),然后存储到另外一个MemoryStream中并且使用其ToArray方法与DataGridView进行绑定

    对于“嵌入式”,示例代码如下:

    [C#]

     public partial class Form1 : Form
    {
    DataGridView dgv = null;

    public Form1()
    {
    InitializeComponent();

    //初始化动态产生数据表等字段
    dgv = new DataGridView();
    dgv.Parent = this;
    dgv.Dock = DockStyle.Fill;

    DataTable dt = new DataTable();
    dt.Columns.Add("Name", typeof(string));
    dt.Columns.Add("Image", typeof(byte[]));
    dt.Rows.Add("Test1", File.ReadAllBytes("d:\\test.jpg"));
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
    dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);
    dgv.AllowUserToAddRows = false;
    dgv.DataSource = dt;
    }

    void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
    if (e.ColumnIndex == 1)
    {
    using (MemoryStream oldms = new MemoryStream((byte[])e.Value))
    {
    Image img = Image.FromStream(oldms);
    Bitmap bt = new Bitmap(img,new Size(100, 100));
    using (MemoryStream newms = new MemoryStream())
    {
    bt.Save(newms,ImageFormat.Jpeg);
    e.Value = newms.ToArray();
    }
    }
    }
    }
    }

    [VB.NET]

    Public Partial Class Form1
    Inherits Form
    Private dgv As DataGridView = Nothing

    Public Sub New()
    InitializeComponent()

    '初始化动态产生数据表等字段
    dgv = New DataGridView()
    dgv.Parent = Me
    dgv.Dock = DockStyle.Fill

    Dim dt As New DataTable()
    dt.Columns.Add("Name", GetType(String))
    dt.Columns.Add("Image", GetType(Byte()))
    dt.Rows.Add("Test1", File.ReadAllBytes("d:\test.jpg"))
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
    AddHandler dgv.CellFormatting,AddressOf New DataGridViewCellFormattingEventHandler(AddressOf dgv_CellFormatting)
    dgv.AllowUserToAddRows = False
    dgv.DataSource = dt
    End Sub

    Private Sub dgv_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs)
    If e.ColumnIndex = 1 Then
    Using oldms As New MemoryStream(DirectCast(e.Value, Byte()))
    Dim img As Image = Image.FromStream(oldms)
    Dim bt As New Bitmap(img, New Size(100, 100))
    Using newms As New MemoryStream()
    bt.Save(newms, ImageFormat.Jpeg)
    e.Value = newms.ToArray()
    End Using
    End Using
    End If
    End Sub
    End Class

    注意我还是沿用了CellFormatting事件,并且请观察该事件内部代码。如果是“连接式”的,只需更改第二列的类型,并且在CellFormatting中读取该列存储的图片路径,转化为byte即可。
    [C#]

     public partial class Form1 : Form
    {
    DataGridView dgv = null;

    public Form1()
    {
    InitializeComponent();

    //初始化动态产生数据表等字段
    dgv = new DataGridView();
    dgv.Parent = this;
    dgv.Dock = DockStyle.Fill;

    DataTable dt = new DataTable();
    dt.Columns.Add("Name", typeof(string));
    dt.Columns.Add("Image", typeof(string));
    dt.Rows.Add("Test1", "d:\\test.jpg");
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;

    dgv.Columns.Add(new DataGridViewTextBoxColumn() { HeaderText = "Name", DataPropertyName = "Name" });
    dgv.Columns.Add(new DataGridViewImageColumn() { HeaderText = "Image", DataPropertyName = "Image" });
    dgv.CellFormatting += new DataGridViewCellFormattingEventHandler(dgv_CellFormatting);
    dgv.AllowUserToAddRows = false;
    dgv.DataSource = dt;
    }

    void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
    if (e.ColumnIndex == 1)
    {
    byte[] bytes = File.ReadAllBytes(e.Value.ToString());
    using (MemoryStream oldms = new MemoryStream(bytes))
    {
    Image img = Image.FromStream(oldms);
    Bitmap bt = new Bitmap(img,new Size(100, 100));
    using (MemoryStream newms = new MemoryStream())
    {
    bt.Save(newms,ImageFormat.Jpeg);
    e.Value = newms.ToArray();
    }
    }
    }
    }
    }

    [VB.NET]

    Public Partial Class Form1
    Inherits Form
    Private dgv As DataGridView = Nothing

    Public Sub New()
    InitializeComponent()

    '初始化动态产生数据表等字段
    dgv = New DataGridView()
    dgv.Parent = Me
    dgv.Dock = DockStyle.Fill

    Dim dt As New DataTable()
    dt.Columns.Add("Name", GetType(String))
    dt.Columns.Add("Image", GetType(String))
    dt.Rows.Add("Test1", "d:\test.jpg")
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells

    dgv.Columns.Add(New DataGridViewTextBoxColumn() With { _
    Key .HeaderText = "Name", _
    Key .DataPropertyName = "Name" _
    })
    dgv.Columns.Add(New DataGridViewImageColumn() With { _
    Key .HeaderText = "Image", _
    Key .DataPropertyName = "Image" _
    })
    AddHandler dgv.CellFormatting,AddressOf New DataGridViewCellFormattingEventHandler(AddressOf dgv_CellFormatting)
    dgv.AllowUserToAddRows = False
    dgv.DataSource = dt
    End Sub

    Private Sub dgv_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs)
    If e.ColumnIndex = 1 Then
    Dim bytes As Byte() = File.ReadAllBytes(e.Value.ToString())
    Using oldms As New MemoryStream(bytes)
    Dim img As Image = Image.FromStream(oldms)
    Dim bt As New Bitmap(img, New Size(100, 100))
    Using newms As New MemoryStream()
    bt.Save(newms, ImageFormat.Jpeg)
    e.Value = newms.ToArray()
    End Using
    End Using
    End If
    End Sub
    End Class
  • 相关阅读:
    Workbox使用策略
    前端性能指标计算方法
    make源文件时出现 /usr/bin/ld: cannot find -lstdc++ 错误
    mac 支持rz sz
    v8引擎的优化
    pixi与lottie-web的benchmark测试
    alinode与官方node性能测试方法及分析
    2019年RTC大会记录
    后端数据推送-EventSource
    技术选型需要关注的软件开源协议
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/2381417.html
Copyright © 2011-2022 走看看