我在下面编写了辅助类,以便在DataGridView
中设置图像动画,但这种图像不起作用(图像不是动画的)。
在此之前,我发现一些示例代码在谷歌上搜索,但它们也没有用。
因为我想了解它是如何工作的,而不是仅仅因为它的工作原因而在我的应用程序中简单地推送一段代码,如果有人能帮助我理解为什么我的代码没有按照预期的那样做,我将不胜感激
我发现了它无法正常工作的原因。源DataTable
本身不包含图像:它们通过其DataGridView
处理程序方法分配给代码中其他位置的CellFormatting
单元格。由于此事件也始终触发,因此始终会传递新的图像对象,因此它始终显示图像的第1帧。当我创建一个存储有原始图像值的新列时,它们会根据需要进行动画处理。
现在的问题是:是否可以为.FormattedValue
的{{1}}事件处理程序方法中分配给DataGridView
属性的图像添加动画效果?< / p>
谢谢。
CellFormatting
答案 0 :(得分:2)
具有自定义单元格的自定义列具有一些优势。
所有设计逻辑都限制在一个地方,可以在设计时使用DataGridView
设计师选择它作为列模板。
表演非常好(用200个动画单元测试),我没有注意到任何闪烁。
动画Gif可以照常拉伸或缩放,使用设计器设置,代码或手动调整行/列的大小。
但是,我不能认为它完整,因为我找不到使用这个自定义Column类方法或属性启动所有动画的好方法。
修改强>
在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
当然这还不够好。还需要进行更多的研究。
这是自定义动画列类:
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