Link to home
Create AccountLog in
Avatar of Dodsworth
Dodsworth

asked on

AJAX style Rating control in a DataGridView Column

As the title says, i'd like to display an AJAX style Rating control in a DataGridView Column.
It doesn't have to 'do' anything... Just display 'Stars'.

Currently my DGV is bound to a table that stores the rating as a string of one to five asterisks .  
Problem is that I want nice big stars rather than oddly aligned asterisks !

Any ideas ?
Avatar of Jorge Paulino
Jorge Paulino
Flag of Portugal image

Avatar of Dodsworth
Dodsworth

ASKER

Ah ha !

I searched for ages to find a link like that !
The reason I failed to find i was that I included 'vb.net' in the search.  Could you VBificate it ?
ASKER CERTIFIED SOLUTION
Avatar of Jorge Paulino
Jorge Paulino
Flag of Portugal image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Right.  How do I add a new column and bind it to my data ?
That I never done it. I just made this changes for you.

I have to look if that's possible or easy handle, but not now. I will try later.
From the example I look at the columns collection and see that the ColumnType property is set to RatingColumn.

I can't find a language reference to ColumnType tho.

Any ideas ?
>> I can't find a language reference to ColumnType tho.

What do you mean with this ? RatingColumn it's build in the code, you don't have language reference.
It's a custom column type ...
Yes if I want to add a rating column in code, say...

Dim myColumn as New DataColumn

Where is the

myColumn.ColumnType

So that I can set the type to be a ratingcolumn ?
To insert the column on the right side of a bound datagridview you can use:
        Dim myRatingColumn As New CustomDataGridViewColumn.RatingColumn
        With myRatingColumn
            .HeaderText = "Rating System"
        End With
        Me.DataGridView1.Columns.Insert(Me.DataGridView1.ColumnCount, myRatingColumn)

Open in new window

Ok I have an empty column now.

How do I bind it ?
As I already post it, it's not easy to bind it with a datasource.

The better method (i think) it to bind with a datasource and then add the column. After this you check when the user changes the rate and you write it on you bound column. It's a workaround that should work fine with some work and validations

ok I have my rating (number) bound column.

How do I set the number of stars in the unbound col ?
You have some columns bound to a datasource and you have added one extra column for the rating. Now you want to show the number of start acording with the bould column, right ?

That's allot of work for only 125 points :)
I assume I'd set the stars on the cellformat event.

But what is the 'star setting' syntax ?
500 greedy but excellent one !
One final thing: do you bind the datagridview using code or by the wizards ?
I don't suppose that I 'bind' really...

I 'fill' like.......

Public Sub fillGrid(ByVal dg As DataGridView, ByVal strSQL As String)
        Dim Ds As DataSet
        Dim cmd As New OleDb.OleDbCommand(strSQL, New OleDb.OleDbConnection(ConnString))
        Dim da As New OleDb.OleDbDataAdapter

        da.SelectCommand = cmd
        Ds = New DataSet
        da.Fill(Ds)
        dg.DataSource = Ds.Tables(0)
        da = Nothing
        Ds = Nothing
        cmd = Nothing
    End Sub

and then set column properties.
Ok, lets try this code:
Imports System.Data.SqlClient
 
Public Class Form1
 
    Const ratingBoundColumn As Byte = 3
 
    Private ratingColumn As Byte
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
        Application.EnableVisualStyles()
        Me.DataGridView1.SuspendLayout()
 
        ' Fill the datagridview (example)
        Dim myConnectionString As String = _
            "Data Source=.\SQLEXPRESS;AttachDbFilename='c:\myDatabase.mdf';" & _
            ";Integrated Security=True;User Instance=True"
        Try
 
            Dim connection As New SqlConnection(myConnectionString)
            Dim SQL As String = "SELECT * FROM myTable;"
 
            Dim da As New SqlDataAdapter(SQL, connection)
            Dim ds As New DataSet
 
            da.Fill(ds, "myTable")
            Me.DataGridView1.DataSource = ds.Tables("myTable").DefaultView
 
            connection.Close()
            connection = Nothing
 
        Catch ex As Exception
            MessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
 
 
        ' Adds the new column to the datagridview
        Dim myRatingColumn As New CustomDataGridViewColumn.RatingColumn
        myRatingColumn.HeaderText = "Rating System"
        Me.DataGridView1.Columns.Insert(Me.DataGridView1.ColumnCount, myRatingColumn)
 
        ' Checks the number of the Rating Column
        ratingColumn = Me.DataGridView1.ColumnCount - 1
 
        ' Loop on all rows as sets the value on the stars
        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
 
        ' You can uncomment the next row after tests
        ' It's to hide de rating bound column
        Me.DataGridView1.Columns(ratingBoundColumn).Visible = False
 
        Me.DataGridView1.ResumeLayout()
 
    End Sub
 
 
    ' Each time you change a star it will write on the bound column
    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
            Dim rc As DataGridViewImageCell
            rc = (CType(Me.DataGridView1(ratingColumn, e.RowIndex), DataGridViewImageCell))
            If rc.Value <> Me.DataGridView1(ratingBoundColumn, e.RowIndex).Value Then
                Me.DataGridView1(ratingBoundColumn, e.RowIndex).Value = rc.Value
            End If
        End If
    End Sub
 
   
End Class

Open in new window

Pasted your code and hooked up the DB...

Data but no Stars !
Is this value right ?

Const ratingBoundColumn As Byte = 3
Yes.
Ok, here you have another example with an unbound datagridview. It works fine with bound or unbound datagrids
Imports System.Data.SqlClient
 
Public Class Form1
 
    Const ratingBoundColumn As Byte = 2
    Private ratingColumn As Byte
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
        Application.EnableVisualStyles()
        Me.DataGridView1.SuspendLayout()
 
        Dim dt As New DataTable
        dt.Columns.Add("ID")
        dt.Columns.Add("Description")
        dt.Columns.Add("Rank")
 
        Dim dr As DataRow
        Dim rnd As New Random
 
        For x As Byte = 0 To 100
            dr = dt.NewRow
            dr.Item("ID") = x.ToString
            dr.Item("Description") = "Item " & x.ToString
            dr.Item("Rank") = rnd.Next(1, 5)
            dt.Rows.Add(dr)
        Next
 
        Me.DataGridView1.DataSource = dt
 
        ' Adds the new column to the datagridview
        Dim myRatingColumn As New CustomDataGridViewColumn.RatingColumn
        myRatingColumn.HeaderText = "Rating System"
        Me.DataGridView1.Columns.Insert(Me.DataGridView1.ColumnCount, myRatingColumn)
 
        ' Checks the number of the Rating Column
        ratingColumn = Me.DataGridView1.ColumnCount - 1
 
        ' Loop on all rows as sets the value on the stars
        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
 
        ' You can uncomment the next row after tests
        ' It's to hide de rating bound column
        Me.DataGridView1.Columns(ratingBoundColumn).Visible = False
 
        Me.DataGridView1.ResumeLayout()
 
    End Sub
 
 
    ' Each time you change a star it will write on the bound column
    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
            Dim rc As DataGridViewImageCell
            rc = (CType(Me.DataGridView1(ratingColumn, e.RowIndex), DataGridViewImageCell))
            If rc.Value <> Me.DataGridView1(ratingBoundColumn, e.RowIndex).Value Then
                Me.DataGridView1(ratingBoundColumn, e.RowIndex).Value = rc.Value
            End If
        End If
    End Sub
   
End Class

Open in new window

Still no stars !

Could the rating class be wrong ?
Give a minute I will upload an example.
Ooops.  I added the resources incorrectly.

Your earlier post worked fine after all !
The "greedy" one as helped you on this. It's not a question of points but to be fair.

Glad I could help you and good luck

jpaulino