Phantom cells in datagrids

D

Dave

Apologies if this has come up before, but I can't find it if it has. I
am fairly new to .Net and am having problems with ghosts in the
datagrid.

Basically I have a find screen that accepts search criteria, then
interrogates a database to find all matching records. These are put
into a dataset, which has a dataview that is used as the datasource of
my datagrid, which is read only. The idea is that the user selects
which record they want to view.

The good news is this all works - well apart from the ghost that is.
Say I run a search that returns 10 records. These all show correctly
in the grid. Say I click on row 9 to highlight it, then go and run a
different search which returns just 5 records. They all display
correctly in the datagrid, then there is a gap and then the previously
highlighted cell remains, just hanging all by itself. It disappears
when you select a real cell, but I can't find any way of getting rid of
this 'ghost' programmatically. Any ideas?

If it helps, this is the code I use to populate the datagrid...



Dim conDatabase As New SqlClient.SqlConnection
Dim commSQL As New SqlClient.SqlCommand
Dim daSQL As New SqlClient.SqlDataAdapter
Dim dsData As New DataSet

conDatabase.ConnectionString = strConnectionString
conDatabase.Open()
commSQL.Connection = conDatabase
commSQL.CommandType = CommandType.StoredProcedure
commSQL.CommandText = "usp_SearchBooks"
' Set parameters
If Me.optTitleAll.Checked = False Then
commSQL.Parameters.Add("@Title", "%" &
Me.txtTitle.Text.Trim & "%")
End If
If Me.optSeriesAll.Checked = False Then
Dim clsComboClass As New ComboClass("", 0)
clsComboClass =
CType(Me.cboSeries.Items(Me.cboSeries.SelectedIndex), ComboClass)
commSQL.Parameters.Add("@SeriesID", clsComboClass.KeyValue)
End If
If Me.optAuthorAll.Checked = False Then
commSQL.Parameters.Add("@Author", "%" &
Me.txtAuthor.Text.Trim & "%")
End If
' run search
daSQL.SelectCommand = commSQL
daSQL.Fill(dsData, "Table")

' Show match list in datagrid.
Dim dvView As New DataView(dsData.Tables(0))
dvView.RowStateFilter = DataViewRowState.OriginalRows
dvView.AllowNew = False
Me.dgResults.DataSource = dvView
conDatabase.Close()



Any help is greatly appreciated.

Cheers

Dave
 
C

Cor Ligthert [MVP]

Dave,

Can you try if it is returning *no* rows.

In the datagrid is used internaly a try and catch to handle that, which is
quiet anoying because it takes some time to find that the first time. So
when you than click to quick than you maybe have this problem.

Just a first thought reading your problem.

Cor
 
D

Dave

Hi Cor

If I run the second search with no results then the datagrid correctly
shows 0 rows, but still shows the 'phantom' cell previously selected.
In this case, with no actual rows to click, there is no way of clearing
the phantom at all. Is this a bug in the datagrid itself?

Cheers

Dave
 
C

Cor Ligthert [MVP]

Dave,

As far as I can see is there something strange in your code.

You add the parameters by a selection.

However than there should be to less parameters be added because if the
checkbox is not checked, than I get the idea that you don't add a parameter.

What do I see wrong (can be a message is not the easiest part to read code)?

Cor
 
D

Dave

Hi Cor

The stored procedure defaults all parameters to null, so any parameters
I don't pass are treated as nulls and ignored by the SP. I have
already established that the calls to the SP return the correct data -
its just the behaviour of the datagrid that is giving me problems.

Cheers

Dave
 
C

Cor Ligthert [MVP]

Dave,

I have never heard about phantom rows in the datagrid. Do you use a special
painting of that.

Did you check the amount of rowviews in your datasource in advance.
something in a check as
messagebox.show(dvView.rows.count.toString) when you set the datasource
everytime.

Cor
 
D

Dave

Hi

I think I left too many distractions in my original question, so here
is an easy way to reproduce the problem...

Create a form and add a datagrid and 2 buttons to it. Cut and paste
the following code and run it. As you see, the load event sets up the
datagrid as I want it, with 2 columns, the first of which is 0 wide.
The first button creates a dataset of 3 records and uses that as the
source for the grid. If you click that you see the 3 rows fine.

The second button does exactly the same thing but with only one record.
If you click row 3 of the grid, then click button 2 you will see the
third row of the OLD grid still displayed (my pkantom) along with the 1
new row.



Public Class Form1
Inherits System.Windows.Forms.Form


#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents DataGrid1 As System.Windows.Forms.DataGrid
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents Button2 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.DataGrid1 = New System.Windows.Forms.DataGrid
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
CType(Me.DataGrid1,
System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'DataGrid1
'
Me.DataGrid1.DataMember = ""
Me.DataGrid1.HeaderForeColor =
System.Drawing.SystemColors.ControlText
Me.DataGrid1.Location = New System.Drawing.Point(381, 36)
Me.DataGrid1.Name = "DataGrid1"
Me.DataGrid1.Size = New System.Drawing.Size(221, 409)
Me.DataGrid1.TabIndex = 0
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(101, 227)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(137, 70)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Button1"
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(99, 360)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(140, 78)
Me.Button2.TabIndex = 2
Me.Button2.Text = "Button2"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(643, 510)
Me.Controls.Add(Me.Button2)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.DataGrid1)
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.DataGrid1,
System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'====================================
' Setup the style for the data grid.
'====================================
Dim dgtsTableStyle As New DataGridTableStyle
dgtsTableStyle.MappingName = "table"

Dim column As New DataGridTextBoxColumn
column.MappingName = "BookID"
column.HeaderText = "BookID"
column.Width = 0
column.ReadOnly = True
dgtsTableStyle.GridColumnStyles.Add(column)
column.Dispose()

Dim column2 As New DataGridTextBoxColumn
column2.MappingName = "Title"
column2.HeaderText = "Title"
column2.Width = 250
column2.ReadOnly = True
dgtsTableStyle.GridColumnStyles.Add(column2)

Me.DataGrid1.TableStyles.Add(dgtsTableStyle)
End Sub

Private Sub button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
'=============================================================
' Fill dataset with 3 records.
'=============================================================
Dim dsExample As New DataSet
Dim tblTable As New DataTable("table")

'===========================
' Set up dataset structure.
'===========================
tblTable.Columns.Add("BookID",
System.Type.GetType("System.Int32"))
tblTable.Columns.Add("Title",
System.Type.GetType("System.String"))
dsExample.Tables.Add(tblTable)

Dim ExampleRow As DataRow = dsExample.Tables("Table").NewRow
ExampleRow("BookID") = 1
ExampleRow("Title") = "Little Women"
dsExample.Tables("Table").Rows.Add(ExampleRow)

Dim ExampleRow2 As DataRow = dsExample.Tables("Table").NewRow
ExampleRow2("BookID") = 2
ExampleRow2("Title") = "The Odessy"
dsExample.Tables("Table").Rows.Add(ExampleRow2)

Dim ExampleRow3 As DataRow = dsExample.Tables("Table").NewRow
ExampleRow3("BookID") = 3
ExampleRow3("Title") = "Gone With the Wind"
dsExample.Tables("Table").Rows.Add(ExampleRow3)

'==================
' Create dataview.
'==================
Dim dvView As New DataView(dsExample.Tables("Table"))
dvView.AllowNew = False
Me.DataGrid1.DataSource = dvView
End Sub

Private Sub button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
'=============================================================
' Fill dataset with 1 record.
'=============================================================
Dim dsExample As New DataSet
Dim tblTable As New DataTable("table")

'===========================
' Set up dataset structure.
'===========================
tblTable.Columns.Add("BookID",
System.Type.GetType("System.Int32"))
tblTable.Columns.Add("Title",
System.Type.GetType("System.String"))
dsExample.Tables.Add(tblTable)

Dim ExampleRow As DataRow = dsExample.Tables("Table").NewRow
ExampleRow("BookID") = 9
ExampleRow("Title") = "A Christmas Carol"
dsExample.Tables("Table").Rows.Add(ExampleRow)

'==================
' Create dataview.
'==================
Dim dvView As New DataView(dsExample.Tables("Table"))
dvView.AllowNew = False
Me.DataGrid1.DataSource = dvView
End Sub

End Class


That's about as clear as I can make it. I appreciate all your efforts
on this, and hope this makes things easier for you.

Many thanks

Dave
 
C

Cor Ligthert [MVP]

Dave,

It is definitly a bug in my opinion.

As far as I can see is this one causing it
column.ReadOnly = True

Removing that one and set this to
dvView.AllowEdit = False

Has in my opinion in the case of your sample the same effect in this case.

It is in VS2005 working as it should

I could not find it on MSDN as a bug, I have placed it as question on
another place.

I will try to tell my actions after this in this messagethread.

Cor
 
B

Bart Mermuys

Hi,

Dave said:
Hi

I think I left too many distractions in my original question, so here
is an easy way to reproduce the problem...

Create a form and add a datagrid and 2 buttons to it. Cut and paste
the following code and run it. As you see, the load event sets up the
datagrid as I want it, with 2 columns, the first of which is 0 wide.
The first button creates a dataset of 3 records and uses that as the
source for the grid. If you click that you see the 3 rows fine.

The second button does exactly the same thing but with only one record.
If you click row 3 of the grid, then click button 2 you will see the
third row of the OLD grid still displayed (my pkantom) along with the 1
new row.

It does look like the bug descibed at the following link, if you assign
nothing as the DataSource the second time then the selected cell sticks too.
http://support.microsoft.com/?id=890211

If you want all columns to be readonly then do what Cor said, otherwise you
could try to select the DataGrid before assigning a new DataSource, it seems
to help, eg:

Me.DataGrid1.Select()
Me.DataGrid1.DataSource = dvView

HTH,
Greetings
 
D

Dave

Gentlemen, I am in your debt. Cor, as you quite rightly pointed out,
if I make the view read only then the problem goes away. In fact when
I do that, as soon as I shift focus off the datagrid the selected row
is unhighlighted anyway. That has fixed my problem

Bart, my problem sounds like it is related to the Microsoft description
and may well have the same route.

Anyway, all is now well with the world. Many thanks indeed :)

Dave
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top