O controlo DataGridView é realmente
muito útil e versátil. Tem inúmeras funcionalidades e diversos tipos de células
(TextBox, ComboBox, Button, etc.) e permite ainda alojar outros tipos personalizados.
A criação de tipos personalizados ou pré-definidos de células permite uma expansão
a este controlo.
Um bom exemplo de criação de células
personalizadas na DataGridView é a criação de uma sistema de classificação ou votação,
onde normalmente se utiliza estrelas para identificar a preferência ou gosto (1
fraco, 5 excelente).

Para implementar este sistema é necessário
adicionar algumas imagens aos Resources
do nosso projecto – 12 para ser preciso). As seguintes imagens poderão ser alteradas,
sendo apenas necessário manter o nome e o tamanho.












Depois, para criar uma coluna/células
de estrelas que permitam a classificação de um determinado item é necessário criar
uma classe que herde as classes DataGridViewImageColumn
e DataGridViewImageCell. Esta classe deverá ter o seguinte código:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Data
Imports System.Text
Imports System.Windows.Forms
' Definição do namespace
Namespace CustomDataGridViewColumn
'
Cria um novo tipo de columa
Public
Class RatingColumn
Inherits DataGridViewImageColumn
' Definições da coluna
Public Sub
New()
Me.CellTemplate =
New RatingCell()
Me.DefaultCellStyle.Alignment
= DataGridViewContentAlignment.MiddleCenter
Me.ValueType =
GetType(Integer)
End Sub
End
Class
' Cria um novo tipo de célula
Public
Class RatingCell
Inherits DataGridViewImageCell
Public
Sub New()
Me.ValueType =
GetType(Integer)
End Sub
' Faz o overrides à função GetFormattedValue retornando a imagem
Protected
Overloads Overrides
Function GetFormattedValue(ByVal
value As Object,
ByVal rowIndex As
Integer, ByRef
cellStyle As DataGridViewCellStyle,
ByVal valueTypeConverter As TypeConverter,
ByVal formattedValueTypeConverter
As TypeConverter, ByVal context
As DataGridViewDataErrorContexts) As
Object
Return starImages(CInt(value))
End Function
' Define o valor por defeito
Public
Overloads Overrides
ReadOnly Property
DefaultNewRowValue() As Object
Get
Return 3
End
Get
End Property
' Faz o overrides ao Paint da imagem
Protected
Overloads Overrides
Sub Paint(ByVal
graphics As Graphics, ByVal
clipBounds As Rectangle, _
ByVal cellBounds
As Rectangle, ByVal
rowIndex As Integer,
ByVal elementState As
DataGridViewElementStates, _
ByVal value
As Object, ByVal formattedValue As
Object, ByVal
errorText As String,
_
ByVal cellStyle
As DataGridViewCellStyle,
ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle,
_
ByVal paintParts
As DataGridViewPaintParts)
Dim cellImage
As Image = DirectCast(formattedValue,
Image)
' Verifica qual a estrela
Dim point
As Point = Me.DataGridView.PointToClient(Control.MousePosition)
Dim starNumber
As Integer = GetStarFromMouse(cellBounds,
point)
' Caso o número seja válido
If
starNumber <> -1 Then
cellImage = starHotImages(starNumber)
End
If
' Suspende
o desenho da selecção
MyBase.Paint(graphics,
clipBounds, cellBounds, rowIndex, elementState, value, _
cellImage, errorText, cellStyle, advancedBorderStyle,
_
(paintParts And
Not DataGridViewPaintParts.SelectionBackground))
End Sub
' Actualiza o valor da
célula quando o utilizador clica na estrela
Protected
Overloads Overrides
Sub OnContentClick(ByVal
e As DataGridViewCellEventArgs)
MyBase.OnContentClick(e)
Dim starNumber
As Integer
Dim x
As Integer = Me.DataGridView.CurrentCellAddress.X
Dim y
As Integer = Me.DataGridView.CurrentCellAddress.Y
Dim ret
As Rectangle = Me.DataGridView.GetCellDisplayRectangle(x,
y, False)
' Verifica qual o valor
starNumber = GetStarFromMouse(ret, Me.DataGridView.PointToClient(Control.MousePosition))
' Caso o número seja válido
If
starNumber <> -1 Then
Me.Value
= starNumber
End
If
End
Sub
' Invalida as células
quando o rato move ou sai
Protected
Overloads Overrides
Sub OnMouseLeave(ByVal
rowIndex As Integer)
MyBase.OnMouseLeave(rowIndex)
Me.DataGridView.InvalidateCell(Me)
End
Sub
Protected Overloads
Overrides Sub
OnMouseMove(ByVal e As
DataGridViewCellMouseEventArgs)
MyBase.OnMouseMove(e)
Me.DataGridView.InvalidateCell(Me)
End Sub
Shared starImages
As Image()
Shared starHotImages
As Image()
Const IMAGEWIDTH
As Integer = 58
' Função que verifica
qual a estrela onde está o rato
Private
Function GetStarFromMouse(ByVal
cellBounds As Rectangle,
ByVal mouseLocation As Point)
As Integer
If
cellBounds.Contains(mouseLocation) Then
Dim mouseXRelativeToCell
As Integer = (mouseLocation.X
- cellBounds.X)
Dim imageXArea
As Integer = (cellBounds.Width
/ 2) - (IMAGEWIDTH / 2)
If ((mouseXRelativeToCell
+ 4) < imageXArea) OrElse (mouseXRelativeToCell
>= (imageXArea + IMAGEWIDTH)) Then
Return
-1
Else
Dim
value As Integer
= CInt(Math.Round(((CSng((mouseXRelativeToCell
- imageXArea + 5)) / CSng(IMAGEWIDTH)) * 5.0F),
MidpointRounding.AwayFromZero))
If
value > 5 OrElse value < 0
Then
System.Diagnostics.Debugger.Break()
End
If
Return
value
End
If
Else
Return -1
End
If
End Function
' Carrega as imagens
Shared Sub
New()
starImages = New Image(5)
{}
starHotImages = New Image(5)
{}
For i
As Integer = 0 To
5
starImages(i) = DirectCast(My.Resources.ResourceManager.GetObject("star"
+ i.ToString()), Image)
Next
For i
As Integer = 0 To
5
starHotImages(i) = DirectCast(My.Resources.ResourceManager.GetObject("starhot"
+ i.ToString()), Image)
Next
End Sub
End Class
End Namespace
Finalmente a implementação!
O seguinte exemplo
utiliza uma lista de musicas que estão numa base de dados. A base de dados está
ligada à DataGridView e existe um campo que é a classificação da música. Ao ser
carregada a lista ou alterada a classificação, será actualizado o respectivo campo
na DataGridView e posterioremente na base de dados.
Para ligar uma base de dados a uma DataGridView podem ver o seguinte exemplo:
Utilizando o controlo DataGridView
No evento Form Load, além de definir a DataSource da DataGridView, é necessário adicionar a nova coluna e indicar quais as classificações actuais.
' Definição da localização da coluna
onde estão as
' classificações - Alterar de acordo
com a coluna
Private
ratingBoundColumn As Byte
= 2
Private ratingColumn As
Byte
Private Sub frmRating_Load(ByVal sender As
System.Object, ByVal e As
System.EventArgs) Handles
MyBase.Load
Application.EnableVisualStyles()
' Suspende a actualização
da DataGridView
Me.DataGridView1.SuspendLayout()
' Definição de dataSource
da datagridview
' ---------------------------------------------------------------------
Me.DataGridView1.DataSource
= ...
' ---------------------------------------------------------------------
' Adiciona a nova coluna
à DataGridView
Dim myRatingColumn
As New CustomDataGridViewColumn.RatingColumn
myRatingColumn.HeaderText = "Classificação"
Me.DataGridView1.Columns.Insert(Me.DataGridView1.ColumnCount,
myRatingColumn)
' Verifica qual o número da coluna
ratingColumn
= Me.DataGridView1.ColumnCount - 1
' Faz um ciclo em todas
as linhas e define o nº de estrelas
For
Each row As DataGridViewRow
In Me.DataGridView1.Rows
If Not
row.IsNewRow Then
Dim rc As DataGridViewImageCell
rc = (CType(Me.DataGridView1(ratingColumn, row.Index), DataGridViewImageCell))
rc.Value = row.Cells(ratingBoundColumn).Value
End
If
Next
' Esconde a coluna onde
se encontra o valor
Me.DataGridView1.Columns(ratingBoundColumn).Visible
= False
' Actualiza a DataGridView
Me.DataGridView1.ResumeLayout()
End
Sub
Depois, quando é alterada alguma classificação,
utilizando o evento CellContentClick
' Sempre que é alterada a classificação
escreve na coluna/célula respectiva
Private
Sub DataGridView1_CellContentClick(ByVal
sender As Object,
ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)
Handles DataGridView1.CellContentClick
If
e.ColumnIndex = ratingColumn And e.RowIndex <>
-1 Then
' Verifica o valor nas coluna de classificação
Dim
rc As DataGridViewImageCell
rc = (CType(Me.DataGridView1(ratingColumn,
e.RowIndex), DataGridViewImageCell))
' Caso o valor seja diferente (seleccionado/existente)
If
rc.Value <> Me.DataGridView1(ratingBoundColumn,
e.RowIndex).Value Then
' Escreve o novo valor
Me.DataGridView1(ratingBoundColumn,
e.RowIndex).Value = rc.Value
End
If
End If
End
Sub
Exemplo do artigo:
DOWNLOAD DO FICHEIRO
PS: Como sempre, qualquer dúvida,
comentário ou correcção ao artigo é sempre bem vinda!
4 comentários:
Boas..
Obrigado por este excelente exemplo..
Programo em VB.NET e tenho acompanhado com interesse este blog.
Que valor guarda na BD para a coluna das imagens?
hola, muy interesante el articulo sabes si podrias poner la demo para descargarla?? te lo agradeceria mucho.. eske intente hacerlo pero me encontre con algunitos errores, tal vez me ekivoke o faltan algunas cosas, spero puedas subirla como descargar.. te lo agradeceria.. :D
gracias de antemano..
Leonardo.
si puedes envialo ami E-mai:
aprendiz_002@hotmail.com
Hola amigo, muchas gracias por subirlo,pero he intentado descargarlo, pero no se puede descargar por mas que intento :(
http://vbtuga.vndv.com/DataGridViewRateStar.zip
se cancela la pagina... :(
spero se pueda areglar, gracias nuevamente
Atte:
Leonardo
aprendiz_002@hotmail.com
Tá muito fixe!.
Obrigado pelo exemplo JPaulino.
Até+
Enviar um comentário