none
DataGridView does not reset when DataSet table is changed.

    Question

  • Hello,

    I am creating a windows forms application with two basic classes for now (more will be added as the application matures). Class A is the windows forms class and Class B is the underlying logic that drives the widgets in class A. Threads in Class A run methods in Class B. The datagridview is updated in a thread safe manner using the following code is Class A:

    1       #region updateStationListDataGridViewThreadSafe  
    2  
    3         public void updateStationListDataGridViewThreadSafe()  
    4         {  
    5             if (stationListDataGridView.InvokeRequired)  
    6             {  
    7                 stationListDataGridView.Invoke(new MethodInvoker(updateStationListDataGridView));  
    8             }  
    9             else 
    10             {  
    11                 updateStationListDataGridView();  
    12             }  
    13         }
    14
    15         #endregion   
    16  
    17         #region updateStationListDataGridView  
    18  
    19         private void updateStationListDataGridView()  
    20         {  
    21             //The following code is used to show the differences between the following.  
    22             int dataGridViewRowsNum = this.stationListDataGridView.Rows.Count;  
    23             int dataSetRowsNum = scrEngine.scrDS.Tables["stationTable"].Rows.Count;  
    24  
    25             //Bind the dataGridView to the table in the specified dataset.  
    26             this.stationListDataGridView.DataSource = scrEngine.scrDS.Tables["stationTable"];  
    27  
    28             //Specify the width of the columns.  
    29             this.stationListDataGridView.Columns["Station Name"].Width = 348;  
    30             this.stationListDataGridView.Columns["Media Type"].Width = 100;  
    31             this.stationListDataGridView.Columns["Bit Rate"].Width = 100;  
    32             this.stationListDataGridView.Columns["Genre"].Width = 125;  
    33             this.stationListDataGridView.Columns["Current Track"].Width = 250;  
    34             this.stationListDataGridView.Columns["Listeners"].Width = 120;  
    35             this.stationListDataGridView.Columns["ID"].Visible = false//This information is available, but not visible.  
    36  
    37             //Set the alignment of these columns to be centered.  
    38             this.stationListDataGridView.Columns["Media Type"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;  
    39             this.stationListDataGridView.Columns["Bit Rate"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;  
    40             this.stationListDataGridView.Columns["Listeners"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;  
    41  
    42             //Do not allow the user to resize the rows.  
    43             this.stationListDataGridView.AllowUserToResizeRows = false;  
    44  
    45             //Get Rid of the ugly row headers.  
    46             this.stationListDataGridView.RowHeadersVisible = false;  
    47  
    48             //If any part of the row is selected, then all cells in the row is selected.  
    49             this.stationListDataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;  
    50  
    51             //Horizontal Rule for each row.  
    52             this.stationListDataGridView.CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal;  
    53  
    54             //Resize the rows automatically.  
    55             this.stationListDataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders;  
    56  
    57             //Set the default font.  
    58             this.stationListDataGridView.DefaultCellStyle.Font = new Font("Tahoma", 8, FontStyle.Regular);  
    59  
    60             //Have no rows selected  
    61             this.stationListDataGridView.ClearSelection();  
    62  
    63         }
    64
    65         #endregion 

    Class B has a dataset that is that is global, and has a table and columns added to it in the following way:

    1         #region Global Variables  
    2  
    3         /// <summary>  
    4         /// Shout Cast Ripper Dataset. This dataset contains in memory tables for the entire application.  
    5         /// </summary>  
    6         public DataSet scrDS = new DataSet();
    7
    8         #endregion  
    9  
    10         #region Constructor  
    11  
    12         /// <summary>  
    13         /// Constructor for shoutCastRipperEngine Class.  
    14         /// </summary>  
    15         public shoutCastRipperEngine()  
    16         {  
    17             //  
    18             //TO DO: Add constructor logic here!  
    19             //  
    20  
    21             this.buildStationTableToSCRDataset();  
    22  
    23         }//End Method shoutCastRipperEngine()  
    24  
    25         #endregion
    26
    27         #region buildStationTableToSCRDataset  
    28  
    29         private void buildStationTableToSCRDataset()  
    30         {  
    31             //Create a table to the scrDS, then create the columns for the table.  
    32             scrDS.Tables.Add("stationTable");  
    33             DataColumn dc;  
    34             dc = new DataColumn("Station Name", System.Type.GetType("System.String"));  
    35             scrDS.Tables["stationTable"].Columns.Add(dc);  
    36             dc = new DataColumn("Media Type", System.Type.GetType("System.String"));  
    37             scrDS.Tables["stationTable"].Columns.Add(dc);  
    38             dc = new DataColumn("Bit Rate", System.Type.GetType("System.Int32"));  
    39             scrDS.Tables["stationTable"].Columns.Add(dc);  
    40             dc = new DataColumn("Genre", System.Type.GetType("System.String"));  
    41             scrDS.Tables["stationTable"].Columns.Add(dc);  
    42             dc = new DataColumn("Current Track", System.Type.GetType("System.String"));  
    43             scrDS.Tables["stationTable"].Columns.Add(dc);  
    44             dc = new DataColumn("Listeners", System.Type.GetType("System.Int32"));  
    45             scrDS.Tables["stationTable"].Columns.Add(dc);  
    46             dc = new DataColumn("ID", System.Type.GetType("System.String"));  
    47             scrDS.Tables["stationTable"].Columns.Add(dc);  
    48  
    49         }
    50
    51         #endregion 

    Each time the user makes a selection from a combobox, the dataSet is updated in Class B with the following code:

    1         #region buildStationListByGenre  
    2  
    3         public void buildStationListByGenre()  
    4         {  
    5             //Variable Declaration  
    6             List<audioStreamInformation> stationList = new List<audioStreamInformation>();  
    7  
    8             scrForm.updatestatusTextBox("Loading...");  
    9  
    10             //Clear all the rows in this table.  
    11             scrDS.Tables["stationTable"].Clear();  
    12  
    13             //Get the selected genre.  
    14             string genre = scrForm.getGenreSelected();  
    15  
    16             //Get the station list information by selected genere.  
    17             this.getStationListByGenre(genre, out stationList);  
    18  
    19             //Populate rows in the specified table in the dataset.  
    20             foreach (audioStreamInformation station in stationList)  
    21             {  
    22                 DataRow rw = scrDS.Tables["stationTable"].NewRow();  
    23                 rw["Station Name"] = station.stationName;  
    24                 rw["Media Type"] = station.mediaType;  
    25                 rw["Bit Rate"] = station.bitRate;  
    26                 rw["Genre"] = station.genre;  
    27                 rw["Current Track"] = station.currentTrack;  
    28                 rw["Listeners"] = station.numListeners;  
    29                 rw["ID"] = station.ID;  
    30                 scrDS.Tables["stationTable"].Rows.Add(rw);  
    31             }  
    32  
    33             scrForm.updateStationListDataGridViewThreadSafe();  
    34  
    35             scrForm.updatestatusTextBox(string.Format("Loaded {0} stations by genre type '{1}'.", scrForm.stationListDataGridView.Rows.Count, genre));  
    36         }
    37
    38         #endregion 

    So the first time the user makes a slection from the comboBox, the datagridview is updated successfully. However, evertime after that I get the following error:

    System.IndexOutOfRangeException: Index 0 does not have a value.

    So for the first pass: 

        dataGridViewRowsNum = 0 
        datSetRowsNum = 113 (the number of expected rows in the dataset)

    For all other passes:

        dataGridViewRowsNum = 623 (this is supposed to be 510, but has 113 extra rows. Why? There might be a data binding problem here.)
        datSetRowsNum = 510 (the number of expected rows in the dataset)

    So, why is the dataGrideVieww keeping rows from all the previous passes? This is should be cleared for each pass and thus the dataGridView should have only the new data it needs for each pass. The only way I can think about solving this is to have the dataGridview use a local dataSet that is created with each pass, instead of using an update global version of the same dataset. So, I know there must a better way to resolve this - and any help would be greatly appreciated.

    Thanks!
        

    • Moved by jack 321 Thursday, July 24, 2008 3:40 AM off topic for C# general
    Sunday, July 20, 2008 5:19 PM

All replies

  • Just as an update, I have cleaned up the code to have an initialize method for the dataGridView. So the method in Class B that is executed in thread is:

    1 #region buildStationListByGenre  
    2  
    3         public void buildStationListByGenre()  
    4         {  
    5             //Variable Declaration  
    6             List<audioStreamInformation> stationList = new List<audioStreamInformation>();  
    7  
    8             scrForm.updatestatusTextBox("Loading...");  
    9  
    10             //Clear all the rows in this table.  
    11             scrDS.Tables["stationTable"].Clear();  
    12  
    13             //Get the selected genre.  
    14             string genre = scrForm.getGenreSelected();  
    15  
    16             //Get the station list information by selected genere.  
    17             this.getStationListByGenre(genre, out stationList);  
    18  
    19             //Populate rows in the specified table in the dataset.  
    20             foreach (audioStreamInformation station in stationList)  
    21             {  
    22                 DataRow rw = scrDS.Tables["stationTable"].NewRow();  
    23                 rw["Station Name"] = station.stationName;  
    24                 rw["Media Type"] = station.mediaType;  
    25                 rw["Bit Rate"] = station.bitRate;  
    26                 rw["Genre"] = station.genre;  
    27                 rw["Current Track"] = station.currentTrack;  
    28                 rw["Listeners"] = station.numListeners;  
    29                 rw["ID"] = station.ID;  
    30                 scrDS.Tables["stationTable"].Rows.Add(rw);  
    31             }  
    32  
    33             scrDS.AcceptChanges();  
    34  
    35             scrForm.updateStationListDataGridViewThreadSafe();  
    36  
    37             scrForm.updatestatusTextBox(string.Format("Loaded {0} stations by genre type '{1}'.", scrForm.stationListDataGridView.Rows.Count, genre));  
    38         }
    39
    40         #endregion 

    And the data is now bound to the dataGridview like this. Please keep in mind that a local copy of the dataset used datagridview is now set as a copy of the dataset from Class B.

            #region updateStationListDataGridView  
     
            private void updateStationListDataGridView()  
            {  
                this.stationListDataSet = scrEngine.scrDS.Copy();  
                //this.stationListDataGridView.DataSource = scrEngine.scrDS.Tables["stationTable"];  
                this.stationListDataGridView.DataSource = stationListDataSet.Tables["stationTable"];  
     
                //Have no rows selected.  
                this.stationListDataGridView.ClearSelection();  
            }
            #endregion 

    This works fine, but I am creating a new dataset each time the datagridview is updated, and I really did not want to do that. I just wanted to use the same global dataset and to update the desired table in the dataset as needed to update the datagridview. I tried to do this in the commented code, but it failed. I have also tried to use the update and refresh methods for the data grid view, and that failed as well. So, got any ideas? Does the datagrdview have a bug, or do I not know how ot code very well?
    Tuesday, July 22, 2008 4:08 AM
  • Discussion in Windows Forms Data Controls and Databinding


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Thursday, July 24, 2008 3:39 AM
  • Please withdraw this post since no one is responding.
    • Marked as answer by John Blair Wednesday, July 30, 2008 4:27 AM
    • Unmarked as answer by John Blair Wednesday, July 30, 2008 4:28 AM
    • Unmarked as answer by John Blair Wednesday, July 30, 2008 4:28 AM
    • Unmarked as answer by John Blair Wednesday, July 30, 2008 4:28 AM
    Wednesday, July 30, 2008 4:27 AM