none
Weird vertical lines when reordering columns in custom datagridview class RRS feed

  • Question

  • I get the vertical lines when I try to reorder columns in a custom datagridview class. Custom datagridview is put into a blank form1. The lines also flicker and later on when I click on form they usually disapear.

    Do you think that could be a paint problem. Does anyone have experience with this kind of behaviour.

    Many thanks for any suggestions.

    Monday, October 30, 2017 11:51 PM

All replies

  • Hi,

    How do you reorder columns in a DataGridView?
    In code, by user action (click on a column header), or other?

    If you reorder it in code, please provide your code.

    Regards,

    Ashidacchi


    • Edited by Ashidacchi Tuesday, October 31, 2017 12:12 AM
    Tuesday, October 31, 2017 12:11 AM
  • Can you post an image of the weird lines?
    Tuesday, October 31, 2017 12:17 AM
  • Hi

    Might be an idea to also post the custom datagridview class code.


    Regards Les, Livingston, Scotland

    Tuesday, October 31, 2017 12:38 AM
  • A small vertical line is the remain of a line (four times the size) as this one. The line appears when column is dragged from its original place and when the drag is over (mouse is UP) this smaller line stays visible. The line also flickers and moves some during the drag... the grey rectangle (of header cell) also flickers during the drag of the column.

    This datagridview is a custom class and can be pulled from the 'tools' in VS. It's what I have been able to create so far (new datagridview class, extended header height, new textboxes that move with columns).

    Since I'm learning... the text of those textboxes represents their names so I can check if the ordering is OK. I colored the one I moved yellow (another check).

    I hope this gives you some more detailed explanation.

    Thanks for all your replies so far.


    PS: Aschidacchi... columns are reordered by a user all these weird effects are visible during reordering(dragging)
    • Edited by halovalo Tuesday, October 31, 2017 8:44 PM
    Tuesday, October 31, 2017 8:38 PM
  • halo,

    So you mean the small vertical line above the dgv, on the form, below the titlebar?

    This line appears when you drag the column? Where does the line come from, do you draw it or is it automatic?

    Long shot: After the drop operation is complete add me.refresh to redraw the form maybe that will erase it.

    I would try to do something else other than stacking controls on top of each other. I think that might somehow do something. Why not put the text boxes above the dgv etc?

    Tuesday, October 31, 2017 10:08 PM
  •  Are you talking about the line i circled below?  If so,  that does not appear to be part of the custom DataGridView.  Do you have code in your Form's Paint event or custom DataGridView's Paint event?  Are you using the CreateGraphics method anywhere in either the Form or custom DataGridView to do any drawing?  Are you using the PaintBackground event of either of them?

     Without us seeing the code and understanding how you are doing any custom drawing in either of these,  it is just a wild guessing game for us suggest a way of fixing it.



    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Tuesday, October 31, 2017 10:12 PM
    Tuesday, October 31, 2017 10:11 PM
  • Hi,

    I cannot hardly know what is the small vertical line. Is it this?
     
    If not, please specify it on your screenshot.
    And provide your code relating with your issur.

    Regards

    Ashidacchi

    Tuesday, October 31, 2017 11:47 PM
  • Here's the code of my custom Datagridview class:

    Public Class DataGridView_Filter
    
        Inherits DataGridView
    
        Public rect As New Rectangle
        Public col As New DataGridViewColumn
        Public row As New DataGridViewRow
        Public tb_ji As TextBox()
        Public tb_ji_new As TextBox()
        Public tb_ji_old As TextBox()
        Public col_index_old As Integer()
        Public col_index_new As Integer()
        Public count_col_index_changed As Integer
        Public mouse_up_bool As Boolean
        Public name_of_tb As String
        Public paintcount As Integer
        Public mouse_down_bool As Boolean
    
    
        Private Sub DataGridView_Filter_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    
            paintcount = paintcount + 1
    
            If paintcount = 1 Then
    
                Me.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing
                Me.ColumnHeadersHeight = 60
                Me.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
    
                tb_ji = {}
                tb_ji_old = {}
                col_index_old = {}
    
                For i = 0 To Columns.Count - 1
    
                    name_of_tb = "TB_" & i.ToString
    
                    Dim tb As New TextBox
                    tb.Name = name_of_tb
                    tb.Text = name_of_tb
                    tb_ji = tb_ji.Concat({tb}).ToArray
                    tb_ji_old = tb_ji
                    col_index_old = col_index_old.Concat({Columns(i).DisplayIndex}).ToArray
    
                    Controls.Add(tb)
    
                    tb.Left = Me.GetColumnDisplayRectangle(i, True).Left + 2
                    tb.Width = Me.GetColumnDisplayRectangle(i, True).Right - Me.GetColumnDisplayRectangle(i, True).Left - 5
                    tb.Top = Me.GetRowDisplayRectangle(0, True).Top - tb.Height - 3
    
                    If i = Me.Columns.Count - 1 Then
    
                        tb.BackColor = Color.Yellow
    
                    End If
    
                Next
    
            Else
    
            End If
    
        End Sub
    
        Private Sub DataGridView_Filter_ColumnWidthChanged(sender As Object, e As DataGridViewColumnEventArgs) Handles Me.ColumnWidthChanged
    
            For i = 0 To Columns.Count - 1
    
                If i = e.Column.Index Then
                    tb_ji(i).Width = Columns(i).Width - 5
                    tb_ji(i).Refresh()
                End If
    
            Next
    
        End Sub
    
    
        Private Sub DataGridView_Filter_ColumnDisplayIndexChanged(sender As Object, e As DataGridViewColumnEventArgs) Handles Me.ColumnDisplayIndexChanged
    
            count_col_index_changed = count_col_index_changed + 1
    
            If count_col_index_changed = 1 Then
    
                tb_ji = tb_ji_old
                col_index_new = {}
                    tb_ji_new = {}
    
                For i = 0 To Me.Columns.Count - 1
    
                        col_index_new = col_index_new.Concat({Columns(i).DisplayIndex}).ToArray
    
                    Next
    
                    For i = 0 To tb_ji.Count - 1
    
                    tb_ji(col_index_new(i)).Left = Me.GetColumnDisplayRectangle(Columns(i).DisplayIndex, True).Left + 2
                    tb_ji(i).Refresh()
    
                Next
                    Me.Refresh()
                    col_index_old = {}
                    For i = 0 To Me.Columns.Count - 1
    
                        col_index_old = col_index_old.Concat({Columns(i).DisplayIndex}).ToArray
    
                    Next
    
                End If
    
            mouse_up_bool = False
    
        End Sub
    
        Private Sub DataGridView_Filter_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
    
            mouse_up_bool = True
            count_col_index_changed = 0
    
        End Sub
    
        Private Sub DataGridView_Filter_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    
            Dim rect As Rectangle
    
            For i = 0 To ColumnCount - 1
    
                rect = GetCellDisplayRectangle(i, -1, True)
    
                If e.Y < rect.Bottom And e.X > rect.Left And e.Y < rect.Top And e.X < rect.Right Then
    
                    Columns(i).HeaderCell.Style.BackColor = Color.DarkGray
    
                End If
    
            Next
    
            Me.Refresh()
    
        End Sub
    
        Private Sub DataGridView_Filter_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    
            mouse_down_bool = True
    
        End Sub
    End Class

    Yes... this is the line you have circled in red. It's larger during dragging but then shortens (or gets hidden behind datagridview object). During drag it also flickers and changes place. Sometimes more than one line is shown.


    In form1.vb I only handle load event with setting the datasource of this Datagridview to existing datatable.
    • Edited by halovalo Wednesday, November 1, 2017 7:35 PM
    Wednesday, November 1, 2017 7:33 PM
  • Halo,

    Maybe the line is caused by the controls you add to the form in the DataGridView_Filter_Paint?

    That should be done in the drag drop event for the control?

    I don't know what you are doing but maybe you should explain what you are doing. What is the purpose of the custom control over a normal dgv?

    Wednesday, November 1, 2017 8:35 PM
  • Hi

    I tried your code with indeterminate result.

    I have only been able to cause the smallline to appear a couple of times having resized the columns, reordered the columns many many times.

    I have been unable to find a definitive action to cause the line to appear, it doesn't seem to be repeatable from actions alone. Repeating an action that seemed to cause the line to appear one time didn't have a similar effect.

    I have not seen any more than one line appear - you say sometimes more than one appears in your testing.

    In my case, the lines were Red rather than Black,yet there are NO Red colors used throughout the code.

    Wonder if it something to do with the System Effects being shadowed in the Form? Just a wild guess.

    Sorry can't help further.


    Regards Les, Livingston, Scotland


    • Edited by leshay Wednesday, November 1, 2017 8:56 PM
    Wednesday, November 1, 2017 8:55 PM
  • Halo,

    Maybe the line is caused by the controls you add to the form in the DataGridView_Filter_Paint?

    That should be done in the drag drop event for the control?

    I don't know what you are doing but maybe you should explain what you are doing. What is the purpose of the custom control over a normal dgv?

    The controls should already be visible when datagridview gets populated. Then these same controls would be manipulated via column reordering event, columnwidthchanged event and horizontal scroll event. The goal is to create such a custom datgridview with these embeded properties from toolbox whenever I choose. So I don't have to manipulate them from extra subs/modules in the forms code.

    Wednesday, November 1, 2017 10:30 PM
  • Les, thank you for trying... you did see the effect though. I can't show you anything else regarding the code because there's none.
    Wednesday, November 1, 2017 10:33 PM
  •  Try adding the code below into your custom DataGridView class.  It seems to stop all the flickering on my end.

     However, this class keeps throwing an index out of range exception in the ColumnWidthChanged event every time i try re-sizing the columns.  Not sure why because,  i am adding a datatable with 3 columns in it as the DataSource in a button click event.  I could not use the Form Load event to do it or it threw a null reference exception in the ColumnDisplayIndexChanged event indicating that the textboxes are Nothing (not created yet).

     I would also recommend not using the number of times the paint event is called to create your textboxes.  If you add one of the controls to the form and use an event that is fired after the form loads,  like a button click event,  the datagridview has already been painted once before the data is added.  That means that there will be no textboxes created.  Instead,  i would test if there is a textbox created for each column yet.  If not,  then create them, or it if there is only one.  If there is,  then skip the creation of it or them.

     Add this code to the class to eliminate the flickering...

        Public Sub New()
            Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw, True)
        End Sub


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Thursday, November 2, 2017 1:04 AM
    Thursday, November 2, 2017 12:22 AM
  •  Oh... i forgot to mention that you should at least check if the Left mouse button is down before executing the code in your MouseDown,  MouseUp,  and MouseMove events.  especially in the MouseMove event.  This alone would stop a lot of the flickering.  You are forcing the DataGridView to repaint itself every time the mousemove event is raised,  even if a colomn is not being moved in any way.

        Private Sub DataGridView_Filter_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    
            If e.Button = MouseButtons.Left Then 'check if the left mouse button is down before executing the code and forcing a repaint
                Dim rect As Rectangle
    
                For i As Integer = 0 To ColumnCount - 1
    
                    rect = GetCellDisplayRectangle(i, -1, True)
    
                    If e.Y < rect.Bottom And e.X > rect.Left And e.Y < rect.Top And e.X < rect.Right Then
    
                        Columns(i).HeaderCell.Style.BackColor = Color.DarkGray
    
                    End If
    
                Next
    
                Me.Refresh()
            End If
    
        End Sub


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Thursday, November 2, 2017 1:06 AM
    Thursday, November 2, 2017 12:31 AM
  • The controls should already be visible when datagridview gets populated. Then these same controls would be manipulated via column reordering event, columnwidthchanged event and horizontal scroll event. The goal is to create such a custom datgridview with these embeded properties from toolbox whenever I choose. So I don't have to manipulate them from extra subs/modules in the forms code.

    halo,

    I don't see the problem (when running your example).

    Just for kicks, whats your screen dpi percentage setting in windows control panel?



    Thursday, November 2, 2017 1:02 AM