Jump to content
  • Advertisement
Sign in to follow this  
Moe

[.net] [solved] DataGridView.Sort is exploding on me....

This topic is 4148 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been trying to figure out this one for the past week, and it has me stumped. In my program I have a DataGridView that shows a list of tasks. To populate the DataGridView I load in a DataTable from a DataSet (using the DataSet.ReadXml method). I then go through each row of the DataTable and generate a corresponding row in the DataGridView, but with a few added columns (for example, an image column based off of a value in one of the other columns). This seems to be working just fine. Right after loading data, I have no problems calling the DataGridView.Sort method - everything works as expected. I am currently sorting by one of two columns (both DataGridViewTextBoxColumns, one with a ValueType of Int32 and one with a ValueType of DataTime). As I mentioned, I am able to sort right off the beginning without any problems. The problem rears it's ugly head if I either add a new row or modify an existing row. When I do this, and call the DataGridView.Sort method (with valid parameters) I get the following exception: Object must be of type Int32 It's the DataGridView.Sort method that is throwing the exception when I attempt to sort by one of the DataGridViewTextBoxColumns that has a ValueType of Int32. I have checked and double checked how the new/modifed rows are being inserted/updated, and everything seems fine in that respect. I am able to sort by other rows (for example my DateTime row), and it works fine. It is only the one column that is causinig problems. Any idea what might be causing this? It has had me stumped for at least a week. Also, is it a bad practice to do what I am doing with the DataGridView? (I don't have it bound to a particular DataSource, but instead I am adding/removing rows directly into/out of the DataGridView. Then when I need to save/load the rows, I parse through it and create a DataTable with similar rows, but without the columns I don't need to save to disk). Any thoughts? I am stumped. [sad] EDIT2: I fixed a one bug. The DataGridView.Sort problem is still there though. EDIT3 - Solved! See my last post! [Edited by - Moe on February 15, 2007 12:08:38 AM]

Share this post


Link to post
Share on other sites
Advertisement
This doesn't happen because you need to add an item that uses IComparable ? (not sure if Int32 has this by default)

EDIT - yes it does, ignore that.

EDIT 2 - if you could post some small repro code, that might help to see exactly what you're doing.

[Edited by - Niksan2 on February 14, 2007 10:28:40 AM]

Share this post


Link to post
Share on other sites
Ok, here is the code that adds a new row. It basically calls a Dialog window that I have set up that gets some basic values, then figures out what bitmap should be displayed according to the priority.

private void CreateNewTask()
{
//show the new task window
NewTaskDialog newTaskDialog = new NewTaskDialog();
DialogResult result = newTaskDialog.ShowDialog();

if (result == DialogResult.OK)
{
//pick out the new task details and add it to the list, then refresh the DataGridView as well
//as update the autosave details
//string newTask = newTaskDialog.Task;
Bitmap newBitmap = NoPriorityBitmap;

if (newTaskDialog.Priority == 0)
newBitmap = NoPriorityBitmap;
if (newTaskDialog.Priority == 1)
newBitmap = LowPriorityBitmap;
if (newTaskDialog.Priority == 2)
newBitmap = MediumPriorityBitmap;
if (newTaskDialog.Priority == 3)
newBitmap = HighPriorityBitmap;


dgvDataGridView.Rows.Insert(dgvDataGridView.Rows.Count, NextTaskId,
newTaskDialog.Priority.ToString(), newBitmap, newTaskDialog.Completed,
newTaskDialog.Task, newTaskDialog.Details, newTaskDialog.DueDateNecessary,
newTaskDialog.DueDate, false);
NextTaskId++;
AutosaveNecessary = true;
SortTodoList(currentSortMode);
UpdateStatusBar();
}


}


Similarily, here is the code that modifies an existing row. It's a bit more complicated (but still shouldn't be hard to understand, especially with all the comments):

//View/Modify a task
private void ViewModifyTask()
{
//grab the id of the task being viewed - pass it into the other window so when it returns we know
//which task was being edited.

//loop through the tasks in the datagrid to find the row with the matching id, and update it (first
//find the row index using a foreach loop, then modify (or delete) the contents of that row with the
//same id. This should allow multiple tasks to be open at the same time

DataGridViewSelectedRowCollection selectedRows = dgvDataGridView.SelectedRows;
foreach (DataGridViewRow selectedRow in selectedRows)
{
//open up a new view window for each row that is selected
frmViewModify modifyDialog = new frmViewModify();

modifyDialog.Id = Int32.Parse(selectedRow.Cells[0].Value.ToString());
modifyDialog.Priority = int.Parse(selectedRow.Cells[1].Value.ToString());
//ignore the priority image, which would be Cells[2]
modifyDialog.Completed = bool.Parse(selectedRow.Cells[3].Value.ToString());
modifyDialog.Task = selectedRow.Cells[4].Value.ToString();
modifyDialog.Details = selectedRow.Cells[5].Value.ToString();
modifyDialog.DueDateNecessary = bool.Parse(selectedRow.Cells[6].Value.ToString());
modifyDialog.DueDate = DateTime.Parse(selectedRow.Cells[7].Value.ToString());

DialogResult result = modifyDialog.ShowDialog();

//depending on the result of the dialog, do different things
if (result == DialogResult.OK)
{
//do something similar to the delete - grab the id out of the modify/view window and use it
//to find the row in the datagrid view, and update it.
Int32 taskId = modifyDialog.Id;
int rowIndex = new int();

foreach (DataGridViewRow row in dgvDataGridView.Rows)
{
if (Int32.Parse(row.Cells[0].Value.ToString()) == taskId)
{
//grab the row index and break
rowIndex = row.Index;
break;
}
}

//now that we have the task index, go through and update each cell of that task using the
//values from the view/modify window
dgvDataGridView.Rows[rowIndex].Cells[1].Value = modifyDialog.Priority.ToString() ;

//set the right image
if (modifyDialog.Priority == 0)
dgvDataGridView.Rows[rowIndex].Cells[2].Value = NoPriorityBitmap;
if (modifyDialog.Priority == 1)
dgvDataGridView.Rows[rowIndex].Cells[2].Value = LowPriorityBitmap;
if (modifyDialog.Priority == 2)
dgvDataGridView.Rows[rowIndex].Cells[2].Value = MediumPriorityBitmap;
if (modifyDialog.Priority == 3)
dgvDataGridView.Rows[rowIndex].Cells[2].Value = HighPriorityBitmap;

dgvDataGridView.Rows[rowIndex].Cells[3].Value = modifyDialog.Completed;
dgvDataGridView.Rows[rowIndex].Cells[4].Value = modifyDialog.Task;
dgvDataGridView.Rows[rowIndex].Cells[5].Value = modifyDialog.Details;
dgvDataGridView.Rows[rowIndex].Cells[6].Value = modifyDialog.DueDateNecessary;
dgvDataGridView.Rows[rowIndex].Cells[7].Value = modifyDialog.DueDate;
dgvDataGridView.Refresh();
//don't touch the OverdueNotified column

SortTodoList(currentSortMode);
AutosaveNecessary = true;
}

//delete the task, if necessary
//NOTE - this is kinda funky, but it works. Check the Delete button for the DialogResult
if (result == DialogResult.Abort)
{
//delete the selected Task - first, figure out what the id of the task was being deleted,
//then find the matching row id in the datagrid and delete that one
int taskId = modifyDialog.Id;
int rowIndex = new int();

foreach (DataGridViewRow row in dgvDataGridView.Rows)
{
if (int.Parse(row.Cells[0].Value.ToString()) == taskId)
{
//grab the row index and break
rowIndex = row.Index;
break;
}
}

//delete the row with that index
dgvDataGridView.Rows.RemoveAt(rowIndex);

SortTodoList(currentSortMode);
AutosaveNecessary = true;
}

//if the dialog result was "Cancel", don't do anything
UpdateStatusBar();
}

}


ViewModifyTask is called when a user right clicks to brinig up a context menu and selects the View/Modify option (hence the name ViewModifyTask).

So far, everything seems to be loading/saving properly. I did a little more testing last night, and it seems to explode only when I try to sort by the priority column. Any other column (including the id column, which is also an Int32) doesn't cause problems. It is probably something simple that I am missing.

If you notice any bad practices in there, please, let me know. I have only ever taken one course in C#, and they really didn't teach us a lot (or at least I don't remember much from it).

Share this post


Link to post
Share on other sites
Holy crap! I just found it! I had:

dgvDataGridView.Rows[rowIndex].Cells[1].Value = modifyDialog.Priority.ToString();


... when I needed...

dgvDataGridView.Rows[rowIndex].Cells[1].Value = Int32.Parse(modifyDialog.Priority.ToString());


Thanks for the help (or the willingness to help)! [smile]

Share this post


Link to post
Share on other sites
:D glad you found it, I always find that I have the "post code and find the bug myself within minutes" all the time, but will only happen when you post it to a forum or newsgroup.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!