Vb.net 在DataGridView中设置图像动画
我在下面编写了helper类,以便在Vb.net 在DataGridView中设置图像动画,vb.net,animation,datagridview,Vb.net,Animation,Datagridview,我在下面编写了helper类,以便在DataGridView中设置图像动画,但该类不起作用(图像未设置动画) 在此之前,我在wen上找到了一些示例代码,但它们也不起作用 我想了解它是如何工作的,而不是仅仅因为它工作就在我的应用程序中插入一段代码。为什么我的代码没有达到预期的效果 编辑 我发现了它不起作用的原因。源DataTable本身不包含图像:它们通过其CellFormatting处理程序方法分配给代码中其他位置的DataGridView单元格。由于此事件也会一直触发,因此始终会传递一个新图像
DataGridView
中设置图像动画,但该类不起作用(图像未设置动画)
在此之前,我在wen上找到了一些示例代码,但它们也不起作用
我想了解它是如何工作的,而不是仅仅因为它工作就在我的应用程序中插入一段代码。为什么我的代码没有达到预期的效果
编辑
我发现了它不起作用的原因。源DataTable
本身不包含图像:它们通过其CellFormatting
处理程序方法分配给代码中其他位置的DataGridView
单元格。由于此事件也会一直触发,因此始终会传递一个新图像对象,因此它始终显示图像的帧#1。当我用存储在其中的本机图像值创建一个新列时,它们会根据需要设置动画
现在的问题是:是否可以在DataGridView
的CellFormatting
事件处理程序方法中设置分配给.FormattedValue
属性的图像动画
Public Class DataGridViewImageAnimator
Private WithEvents MyDataGridView As DataGridView
Public Sub New(dataGridView As DataGridView)
MyDataGridView = dataGridView
End Sub
Private MyAnimatedImages As New Dictionary(Of Point, Image)
Private Sub ImageAnimator_FrameChanged(sender As Object, e As EventArgs)
Dim imageCells = MyDataGridView.Rows.Cast(Of DataGridViewRow).SelectMany(
Function(dgvr) dgvr.Cells.OfType(Of DataGridViewImageCell))
For Each cell In imageCells
Dim img = TryCast(cell.FormattedValue, Image)
If img IsNot Nothing AndAlso MyAnimatedImages.ContainsValue(img) Then
MyDataGridView.InvalidateCell(cell)
End If
Next
End Sub
Private Sub MyDataGridView_CellPainting(
sender As Object,
e As DataGridViewCellPaintingEventArgs
) Handles MyDataGridView.CellPainting
If e.ColumnIndex >= 0 AndAlso e.RowIndex >= 0 Then
Dim cell = MyDataGridView(e.ColumnIndex, e.RowIndex)
Dim drawPoint = MyDataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True).Location
Dim pt = New Point(e.ColumnIndex, e.RowIndex)
Dim cellImg = TryCast(cell.FormattedValue, Image)
If MyAnimatedImages.ContainsKey(pt) AndAlso Equals(MyAnimatedImages(pt), cellImg) Then
'If image is already registered as animated, and is still in cell
ImageAnimator.UpdateFrames()
e.Graphics.DrawImage(cellImg, drawPoint)
Else
If MyAnimatedImages.ContainsKey(pt) Then
'If image registered as animated is no longer in cell
ImageAnimator.StopAnimate(MyAnimatedImages(pt), AddressOf ImageAnimator_FrameChanged)
MyAnimatedImages.Remove(pt)
End If
If cellImg IsNot Nothing AndAlso ImageAnimator.CanAnimate(cellImg) Then
'If cell contains an image not yet registered as animated
MyAnimatedImages(pt) = cellImg
ImageAnimator.Animate(MyAnimatedImages(pt), AddressOf ImageAnimator_FrameChanged)
ImageAnimator.UpdateFrames()
e.Graphics.DrawImage(cellImg, drawPoint)
End If
End If
End If
End Sub
End Class
带有自定义单元格的自定义列提供了一些优势。
所有设计逻辑都限制在一个地方,可以在设计时使用
DataGridView
designer将其选择为列模板。性能非常好(用200个动画单元格测试),我没有注意到任何闪烁。
可以使用设计器设置,通过编码或手动调整行/列的大小,像往常一样拉伸或缩放动画GIF。
<>但是,我不能认为它是完整的,因为我找不到一个好的方法来启动所有的动画使用这个自定义的列类方法或属性。 编辑:
向
DataGridView
(DataGridView.Animate()
)添加了扩展方法。这允许隐藏失效过程。
DataGridView
数据绑定完成后,只需调用扩展方法:DataGridView1.DataSource = [DataSource]
DataGridView1.Animate()
Imports System.Runtime.CompilerServices
Module DGVExtesions
<Extension()>
Public Sub Animate(ByVal AnimatedGrid As DataGridView)
Try
For Each row As DataGridViewRow In AnimatedGrid.Rows
For Each cell As DataGridViewCell In row.Cells.OfType(Of AnimatedDGVColumn.AnimatedCell)()
AnimatedGrid.InvalidateCell(cell)
Next
Next
Catch ex As Exception
Trace.WriteLine("Exception: {0}", ex.Message)
End Try
End Sub
End Module
包含扩展方法的模块:DataGridView1.DataSource = [DataSource]
DataGridView1.Animate()
Imports System.Runtime.CompilerServices
Module DGVExtesions
<Extension()>
Public Sub Animate(ByVal AnimatedGrid As DataGridView)
Try
For Each row As DataGridViewRow In AnimatedGrid.Rows
For Each cell As DataGridViewCell In row.Cells.OfType(Of AnimatedDGVColumn.AnimatedCell)()
AnimatedGrid.InvalidateCell(cell)
Next
Next
Catch ex As Exception
Trace.WriteLine("Exception: {0}", ex.Message)
End Try
End Sub
End Module
导入System.Runtime.CompilerServices
模块dgvextensions
公共子动画(ByVal AnimatedGrid作为DataGridView)
尝试
对于AnimatedGrid.Rows中作为DataGridViewRow的每一行
对于类型为(AnimatedDGVColumn.AnimatedCell的)()的行.Cells.Of中作为DataGridViewCell的每个单元格
AnimatedGrid.InvalidateCell(单元格)
下一个
下一个
特例
WriteLine(“异常:{0}”,例如Message)
结束尝试
端接头
端模块
当然,这还不够好。需要更多的研究。这是自定义的动画列类:
Imports System.ComponentModel
Imports System.Windows.Forms
Public Class AnimatedDGVColumn
Inherits System.Windows.Forms.DataGridViewColumn
Private custCellTemplate As AnimatedCell
Public Sub New()
Me.custCellTemplate = New AnimatedCell
Me.custCellTemplate.ImageLayout = DataGridViewImageCellLayout.Zoom
MyBase.CellTemplate = custCellTemplate
Me.AutoSizeMode = DataGridViewAutoSizeColumnMode.None
Me.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
End Sub
<Description("The ImageLayout in the Cells for this Column"), Category("Appearance")> _
<EditorBrowsable(EditorBrowsableState.Always), Browsable(True)>
Public Property ImageLayout As DataGridViewImageCellLayout
Get
Return Me.custCellTemplate.ImageLayout
End Get
Set(ByVal value As DataGridViewImageCellLayout)
Me.custCellTemplate.ImageLayout = value
End Set
End Property
Public Overloads Property CellTemplate As AnimatedCell
Get
Return Me.custCellTemplate
End Get
Set(value As AnimatedCell)
Me.custCellTemplate = value
MyBase.CellTemplate = value
End Set
End Property
Public Class AnimatedCell
Inherits System.Windows.Forms.DataGridViewImageCell
Private Animation As Image
Private IsAnimating As Boolean
Public Sub New()
Me.Animation = Nothing
Me.IsAnimating = False
End Sub
Public Overloads Property ImageLayout() As DataGridViewImageCellLayout
Get
Return MyBase.ImageLayout
End Get
Set(ByVal value As DataGridViewImageCellLayout)
MyBase.ImageLayout = value
End Set
End Property
Protected Overrides Sub Paint(graphics As Graphics, clipBounds As Rectangle, cellBounds As Rectangle, rowIndex As Integer, elementState As DataGridViewElementStates, value As Object, formattedValue As Object, errorText As String, cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle, paintParts As DataGridViewPaintParts)
If (IsDBNull(value)) OrElse (value Is Nothing) Then Return
If Me.Animation Is Nothing Then
Me.Animation = CType(formattedValue, Image)
End If
Animate()
ImageAnimator.UpdateFrames()
MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, Nothing, Me.Animation, errorText, cellStyle, advancedBorderStyle, paintParts)
End Sub
Private Sub Animate()
If Me.IsAnimating = True Then Return
If (Me.Animation IsNot Nothing) AndAlso ImageAnimator.CanAnimate(Me.Animation) = True Then
ImageAnimator.Animate(Me.Animation, AddressOf Me.RotateFrame)
Me.IsAnimating = True
End If
End Sub
Private Sub RotateFrame(o As Object, e As EventArgs)
If Me.RowIndex > -1 Then
Me.DataGridView.InvalidateCell(Me)
End If
End Sub
Public Overrides Function Clone() As Object
Dim result As AnimatedCell = New AnimatedCell With {
.IsAnimating = False,
.Animation = Nothing,
.ImageLayout = Me.ImageLayout
}
Return result
End Function
End Class
End Class
导入System.ComponentModel
导入System.Windows.Forms
公共类动画列
继承System.Windows.Forms.DataGridViewColumn
私有custCellTemplate作为AnimatedCell
公共分新()
Me.custCellTemplate=新的AnimatedCell
Me.custCellTemplate.ImageLayout=DataGridViewImageCellLayout.Zoom
MyBase.CellTemplate=custCellTemplate
Me.AutoSizeMode=DataGridViewAutoSizeColumnMode.None
Me.DefaultCellStyle.Alignment=DataGridViewContentAlignment.MiddleCenter
端接头
_
公共属性ImageLayout作为DataGridViewImageCellLayout
得到
Return Me.custCellTemplate.ImageLayout
结束
设置(ByVal值为DataGridViewImageCellLayout)
Me.custCellTemplate.ImageLayout=值
端集
端属性
Public将属性CellTemplate重载为AnimatedCell
得到
返回给我
结束
设置(值为AnimatedCell)
Me.custCellTemplate=值
MyBase.CellTemplate=值
端集
端属性
公共类动画单元
继承System.Windows.Forms.DataGridViewImageCell
作为图像的私有动画
私有IsAnimating为布尔值
公共分新()
我。动画=什么都没有
Me.IsAnimating=False
端接头
Public将属性ImageLayout()重载为DataGridViewImageCellLayout
得到
返回MyBase.ImageLayout
结束
设置(ByVal值为DataGridViewImageCellLayout)
MyBase.ImageLayout=值
端集
端属性
保护覆盖子漆(图形为图形,剪贴簿为矩形,单元格边框为矩形,行索引为整数,elementState为DataGridViewElementState,值为对象,格式化值为对象,错误文本为字符串,单元格样式为DataGridViewCellStyle,advancedBorderStyle为DataGridViewAdvancedBorderStyle,paintParts为DataGridViewPaintParts)
如果(IsDBNull(value))或(value为Nothing),则返回
如果是我,动画什么都不是
Me.Animation=CType(formattedValue,Image)
如果结束
制作动画()
ImageAnimator.UpdateFlames()
画图(图形、剪贴簿、单元格边框、行索引、元素状态、无、Me.Animation、errorText、单元格样式、高级边框样式、画图部件)
端接头
私有子动画()
如果Me.IsAnimating=True,则返回
如果(Me.Animation不是空的)和ImageAnimator.CanAnimate(Me.Animation)=True,则
ImageAnimator.Animate(Me.Animation,AddressOf Me.RotateFrame)
真的
如果结束
端接头
私有子RotateName(o作为对象,e作为事件参数)
如果Me.RowIndex>-1,则
Me.DataGridView.InvalidateCell(Me)
如果结束
端接头
公共重写函数Clone()作为对象
将结果变暗为AnimatedCell=新的AnimatedCell{
.IsAnimating=False,