在DataGridView中动画图像

时间:2018-04-08 12:40:31

标签: vb.net animation datagridview

我在下面编写了辅助类,以便在DataGridView中设置图像动画,但这种图像不起作用(图像不是动画的)。

在此之前,我发现一些示例代码在谷歌上搜索,但它们也没有用。

因为我想了解它是如何工作的,而不是仅仅因为它的工作原因而在我的应用程序中简单地推送一段代码,如果有人能帮助我理解为什么我的代码没有按照预期的那样做,我将不胜感激

修改

我发现了它无法正常工作的原因。源DataTable本身不包含图像:它们通过其DataGridView处理程序方法分配给代码中其他位置的CellFormatting单元格。由于此事件也始终触发,因此始终会传递新的图像对象,因此它始终显示图像的第1帧。当我创建一个存储有原始图像值的新列时,它们会根据需要进行动画处理。

现在的问题是:是否可以为.FormattedValue的{​​{1}}事件处理程序方法中分配给DataGridView属性的图像添加动画效果?< / p>

谢谢。

CellFormatting

1 个答案:

答案 0 :(得分:2)

具有自定义单元格的自定义列具有一些优势。

所有设计逻辑都限制在一个地方,可以在设计时使用DataGridView设计师选择它作为列模板。

Animated Column in design mode


表演非常好(用200个动画单元测试),我没有注意到任何闪烁。

动画Gif可以照常拉伸或缩放,使用设计器设置,代码或手动调整行/列的大小。

enter image description here

但是,我不能认为它完整,因为我找不到使用这个自定义Column类方法或属性启动所有动画的好方法。

修改
DataGridViewDataGridView.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