Home All Groups Group Topic Archive Search About

Changing datagridview cells borders at runtime

Author
18 Jun 2006 5:55 AM
steve
Hi All

I urgently need help on setting datagridview cell borders at runtime

I found some code on the web from
Programming Smart Client Data Applications with .NET 2.0
by Brian Noyes
See below

This is what I have been trying to achieve, but when I run it ALL the cell
Top borders go from inset to feint white on ALL cells, ALL rows

If I change the line (marked *******) to false then the borders are OK but
obviously no hiding of the required cell top borders

I am completely lost on what is wrong

Any help greatly appreciated

Regards
Steve

Public Class GroupByGrid

Inherits DataGridView

Public Sub New()

With Me

..AdvancedCellBorderStyle.All = DataGridViewAdvancedCellBorderStyle.Inset

End With

End Sub

Protected Overrides Sub OnCellFormatting(ByVal args As
DataGridViewCellFormattingEventArgs)

' Call home to base

MyBase.OnCellFormatting(args)

' First row always displays

If args.RowIndex = 0 Then

Return

End If

If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then

args.Value = String.Empty

args.FormattingApplied = True

End If

End Sub

Private Function IsRepeatedCellValue(ByVal rowIndex As Integer, ByVal
colIndex As Integer) As Boolean

Dim currCell As DataGridViewCell = Rows(rowIndex).Cells(colIndex)

Dim prevCell As DataGridViewCell = Rows(rowIndex - 1).Cells(colIndex)

If Not IsNothing(currCell) AndAlso Not IsNothing(prevCell) AndAlso Not
IsNothing(currCell.Value) AndAlso Not IsNothing(prevCell.Value) Then

If (currCell.Value.ToString() = prevCell.Value.ToString() OrElse
currCell.Value.Equals(prevCell.Value)) And prevCell.Value.ToString <>
String.Empty And currCell.Value.ToString <> String.Empty Then

Return true **********************************************

Else

Return False

End If

Else

Return False

End If

End Function

Protected Overrides Sub OnCellPainting(ByVal args As
DataGridViewCellPaintingEventArgs)

MyBase.OnCellPainting(args)

' Ignore column and row headers and first row

If args.RowIndex < 1 OrElse args.ColumnIndex < 0 Then

Return

End If

If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then

args.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None

Else

args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top

End If



End Sub

End Class

Author
18 Jun 2006 6:44 AM
Cor Ligthert [MVP]
steve,

I gave you the solution that was used in past with a datagrid, did you try
that?

Cor

Show quoteHide quote
"steve" <ga630sf@newsgroups.nospam> schreef in bericht
news:eNrDUvpkGHA.1204@TK2MSFTNGP02.phx.gbl...
> Hi All
>
> I urgently need help on setting datagridview cell borders at runtime
>
> I found some code on the web from
> Programming Smart Client Data Applications with .NET 2.0
> by Brian Noyes
> See below
>
> This is what I have been trying to achieve, but when I run it ALL the cell
> Top borders go from inset to feint white on ALL cells, ALL rows
>
> If I change the line (marked *******) to false then the borders are OK but
> obviously no hiding of the required cell top borders
>
> I am completely lost on what is wrong
>
> Any help greatly appreciated
>
> Regards
> Steve
>
> Public Class GroupByGrid
>
> Inherits DataGridView
>
> Public Sub New()
>
> With Me
>
> .AdvancedCellBorderStyle.All = DataGridViewAdvancedCellBorderStyle.Inset
>
> End With
>
> End Sub
>
> Protected Overrides Sub OnCellFormatting(ByVal args As
> DataGridViewCellFormattingEventArgs)
>
> ' Call home to base
>
> MyBase.OnCellFormatting(args)
>
> ' First row always displays
>
> If args.RowIndex = 0 Then
>
> Return
>
> End If
>
> If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then
>
> args.Value = String.Empty
>
> args.FormattingApplied = True
>
> End If
>
> End Sub
>
> Private Function IsRepeatedCellValue(ByVal rowIndex As Integer, ByVal
> colIndex As Integer) As Boolean
>
> Dim currCell As DataGridViewCell = Rows(rowIndex).Cells(colIndex)
>
> Dim prevCell As DataGridViewCell = Rows(rowIndex - 1).Cells(colIndex)
>
> If Not IsNothing(currCell) AndAlso Not IsNothing(prevCell) AndAlso Not
> IsNothing(currCell.Value) AndAlso Not IsNothing(prevCell.Value) Then
>
> If (currCell.Value.ToString() = prevCell.Value.ToString() OrElse
> currCell.Value.Equals(prevCell.Value)) And prevCell.Value.ToString <>
> String.Empty And currCell.Value.ToString <> String.Empty Then
>
> Return true **********************************************
>
> Else
>
> Return False
>
> End If
>
> Else
>
> Return False
>
> End If
>
> End Function
>
> Protected Overrides Sub OnCellPainting(ByVal args As
> DataGridViewCellPaintingEventArgs)
>
> MyBase.OnCellPainting(args)
>
> ' Ignore column and row headers and first row
>
> If args.RowIndex < 1 OrElse args.ColumnIndex < 0 Then
>
> Return
>
> End If
>
> If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then
>
> args.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None
>
> Else
>
> args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top
>
> End If
>
>
>
> End Sub
>
> End Class
>
>
Author
19 Jun 2006 12:31 PM
Linda Liu [MSFT]
Hi Steve,

Thank you for posting.

I perfomed a test based on your code and reproduce the problem you have
described. Through debugging, I found out the following facts:

1. Once you changed the args.AdvancedBorderStyle.Top to
DataGridViewAdvancedCellBorderStyle.None in the OnCellPainting method, the
AdvancedBorderStyle.Top of the DataGridView is changed to
DataGridViewAdvancedCellBorderStyle.None too.

2. Once the AdvancedBorderStyle.Top of the DataGridView has been changed to
a different value from previous, the CellPainting event of the DataGridView
will be raised automatically. Thus the OnCellPainting method is called. All
cells in the DataGridView will be in the same border style at last.

These two facts explain why the problem occurs.

I have tried modifying the statement
"args.AdvancedBorderStyle.Top=AdvancedCellBorderStyle.Top" to
the "args.AdvancedBorderStyle.Top =
DataGridViewAdvancedCellBorderStyle.Inset". When running, the result turned
out to be correct--only those cells having the same value hide their top
borders. However, the DataGridView seems to be dithering. The
OnCellPainting method is being called again an again and this calling seems
to never stop. So this modification is not good.

It seems that we have to do this on other way. I will go on researching
this issue. I appreciate your patience.



Sincerely,
Linda Liu
Microsoft Online Community Support

====================================================
When responding to posts,please "Reply to Group" via
your newsreader so that others may learn and benefit
from your issue.
====================================================
Author
21 Jun 2006 6:29 AM
Jeffrey Tan[MSFT]
Hi steve,

Have you read my reply to you in your another post? You'd better override
AdjustCellBorderStyle method to achieve this task. If you still have any
concern, please feel free to followup me in that post. Thanks!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
21 Jun 2006 7:15 AM
steve
Hi Jeff

Thanks for all your efforts on this topic

I hadn't seen your final reply to my old post on this topic but have now
printed it and looking into it

I have been able to get what I want using an override onpaint event but it
only works when the border style is set to single
(see prev reply on this thread from Linda Liu)
and I would prefer to use raised or sunken

Kind regards anyway
Steve


""Jeffrey Tan[MSFT]"" <je***@online.microsoft.com> wrote in message
Show quoteHide quote
news:yu1JSwPlGHA.4928@TK2MSFTNGXA01.phx.gbl...
> Hi steve,
>
> Have you read my reply to you in your another post? You'd better override
> AdjustCellBorderStyle method to achieve this task. If you still have any
> concern, please feel free to followup me in that post. Thanks!
>
> Best regards,
> Jeffrey Tan
> Microsoft Online Community Support
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
>
Author
22 Jun 2006 10:36 AM
Jeffrey Tan[MSFT]
Hi Steve,

Thanks for your feedback!

Yes, based on my test, you can use CellPainting event to change certain
cell's border style, sample code snippet is listed below:
Public Class Form1

    Private Sub DataGridView1_CellPainting(ByVal sender As System.Object,
ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles
DataGridView1.CellPainting
        If e.RowIndex = 2 And e.ColumnIndex = 1 Then
            Me.DataGridView1.AdvancedCellBorderStyle.Bottom =
DataGridViewAdvancedCellBorderStyle.None
            Me.DataGridView1.AdvancedCellBorderStyle.Top =
DataGridViewAdvancedCellBorderStyle.Inset
        ElseIf e.RowIndex = 3 And e.ColumnIndex = 1 Then
            Me.DataGridView1.AdvancedCellBorderStyle.Bottom =
DataGridViewAdvancedCellBorderStyle.Inset
            Me.DataGridView1.AdvancedCellBorderStyle.Top =
DataGridViewAdvancedCellBorderStyle.None
        Else
            Me.DataGridView1.AdvancedCellBorderStyle.Bottom =
DataGridViewAdvancedCellBorderStyle.Inset
            Me.DataGridView1.AdvancedCellBorderStyle.Top =
DataGridViewAdvancedCellBorderStyle.Inset
        End If
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
        Dim dt As New DataTable
        dt.Columns.Add(New DataColumn("column1", GetType(Integer)))
        dt.Columns.Add(New DataColumn("column2", GetType(String)))

        Dim i As Integer
        For i = 0 To 4
            Dim dr As DataRow = dt.NewRow()
            dr("column1") = i
            dr("column2") = "item" & i.ToString()
            dt.Rows.Add(dr)
        Next

        Me.DataGridView1.AdvancedCellBorderStyle.All =
DataGridViewAdvancedCellBorderStyle.Inset
        Me.DataGridView1.DataSource = dt

    End Sub
End Class

You may give it a try. I have also attached my sample project in this
reply, for your information.

Hope it helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
26 Jun 2006 10:20 AM
Jeffrey Tan[MSFT]
Hi Steve,

Have you recieved my sample project? Does it make sense to you? If you
still need any help, please feel free to tell me.

Additionally, I found that there is some strange performance issue in my
sample project. After performing some debugging I found that changing
DataGridView.AdvancedCellBorderStyle property in CellPainting event will
generate another WM_PAINT message and send to DataGridView, which will
force another painting in DataGridView(again calls CellPainting event ), so
the DataGridView UI will keep painting all the time and have a flicker UI.

To resolve this issue, you may place a ValidateRect Win32 calling in
CellPainting event, which removes the WM_PAINT message in the message
queue. Attached is the modified sample project, which works well now. Hope
it helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
28 Jun 2006 3:33 AM
steve
Hi Jeff

I hadn't looked at this group for a while assuming the thread was at an end

I have tried the code you attached but I get an error message at the
ValidateRect(Me.DataGridView1.Handle, Nothing) line

A call to PInvoke function
'DataGridViewPainting!DataGridViewPainting.Form1::ValidateRect' has
unbalanced the stack. This is likely because the managed PInvoke signature
does not match the unmanaged target signature. Check that the calling
convention and parameters of the PInvoke signature match the target
unmanaged signature.



Regards

Steve



""Jeffrey Tan[MSFT]"" <je***@online.microsoft.com> wrote in message
Show quoteHide quote
news:ij7huoQmGHA.4928@TK2MSFTNGXA01.phx.gbl...
> Hi Steve,
>
> Have you recieved my sample project? Does it make sense to you? If you
> still need any help, please feel free to tell me.
>
> Additionally, I found that there is some strange performance issue in my
> sample project. After performing some debugging I found that changing
> DataGridView.AdvancedCellBorderStyle property in CellPainting event will
> generate another WM_PAINT message and send to DataGridView, which will
> force another painting in DataGridView(again calls CellPainting event ),
> so
> the DataGridView UI will keep painting all the time and have a flicker UI.
>
> To resolve this issue, you may place a ValidateRect Win32 calling in
> CellPainting event, which removes the WM_PAINT message in the message
> queue. Attached is the modified sample project, which works well now. Hope
> it helps!
>
> Best regards,
> Jeffrey Tan
> Microsoft Online Community Support
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
Author
29 Jun 2006 9:50 AM
Jeffrey Tan[MSFT]
Hi Steve,

Thanks for your feedback!

Oh, yes, I original tested the project in release build which can not see
this error. By testing it under debugger, I can see this error. The error
is caused by an improper API declaration: the second parameter to
ValidateRect should be ByRef instead of ByVal. However, after correcting
this error, it seems that it does not take effect. So it seems that
ValidateRect can not remove WM_PAINT message from the message queue.

Currently, I think the only valid solution is overriding
AdjustCellBorderStyle method in DataGridViewCell and return a customized
cell. I have written a sample project to demonstrate this technology,
please see the attachment. Just click the button on the Form to see the
effect.

Hope it helps!

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
5 Jul 2006 7:01 AM
steve
Hi Jeffrey

Thanks for the help on this topic

I have got it working just fine

Regards
Steve
""Jeffrey Tan[MSFT]"" <je***@online.microsoft.com> wrote in message
Show quoteHide quote
news:J9y4CG2mGHA.5268@TK2MSFTNGXA01.phx.gbl...
> Hi Steve,
>
> Thanks for your feedback!
>
> Oh, yes, I original tested the project in release build which can not see
> this error. By testing it under debugger, I can see this error. The error
> is caused by an improper API declaration: the second parameter to
> ValidateRect should be ByRef instead of ByVal. However, after correcting
> this error, it seems that it does not take effect. So it seems that
> ValidateRect can not remove WM_PAINT message from the message queue.
>
> Currently, I think the only valid solution is overriding
> AdjustCellBorderStyle method in DataGridViewCell and return a customized
> cell. I have written a sample project to demonstrate this technology,
> please see the attachment. Just click the button on the Form to see the
> effect.
>
> Hope it helps!
>
> Best regards,
> Jeffrey Tan
> Microsoft Online Community Support
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
> This posting is provided "AS IS" with no warranties, and confers no
> rights.
Author
6 Jul 2006 1:57 AM
Jeffrey Tan[MSFT]
You are welcome.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.