I wrote the helper class below in order to animate images in a DataGridView
, which is not working (images aren't animated).
Before that, I found some sample code on the wen, but they didn't work either.
I want to understand how this works instead of simply shove a piece of code inside my app just because it works. Why does my code not do what it is expected to?
Edit
I discovered the reason why it isn't working. The source DataTable
itself don't contain images: they are assigned to DataGridView
's Cells elsewhere in the code by its CellFormatting
handler method. Since this event also triggers all the time, a fresh image object is always passed, so it keeps always showing the image's frame #1. When I created a new column with native image values stored in it, they animated as desired.
The question now is: is it possible to animate images that are assigned to the .FormattedValue
property inside DataGridView
's CellFormatting
event handler method?
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
See Question&Answers more detail:os