tags:

views:

2468

answers:

3

I have a WinForms application with a DataGridView control and a column of DataGridViewButtonCell cells within that. When I click on one of these buttons, it starts a background task, and I'd like to disable the buttons until that task completes.

I can disable the DataGridView control, but it gives no visual indication that the buttons are disabled. I want the user to see that the buttons are disabled, and to notice that the task has finished when the buttons are enabled again.

Bonus points for a method that allows me to disable the buttons individually, so I can leave one of the buttons enabled while the task runs. (Note that I can't actually give out bonus points.)

+1  A: 

Here's the best solution I've found so far. This MSDN article gives the source code for a cell class that adds an Enabled property.

It works reasonably well, but there are two gotchas:

  1. You have to invalidate the grid after setting the Enabled property on any cells. It shows that in the sample code, but I missed it.
  2. It's only a visual change, setting the Enabled property doesn't actually enable or disable the button. The user can still click on it. I could check the enabled property before executing the click event, but it also seemed to be messing up the appearance when the user clicked on it. Instead, I just disabled the entire grid. That works alright for me, but I'd prefer a method that allows me to disable some buttons without disabling the entire grid.
Don Kirkby
+1  A: 

Another example using the same concept as the MSDN article linked by Don.

hometoast
+1  A: 

You could give this a try:

When you click on the cell...

  1. Check to see if the process with the current row identifier is running from a class-level list; if so, exit the cell click event.
  2. Store the row identifier in the class-level list of running processes.
  3. Change the button text to "Running..." or something appropriate.
  4. Attach a basic RunWorkerCompleted event handler to your process (explained shortly).
  5. Call backgroundWorker.RunWorkerAsync(rowIdentifier).

In the DoWork event handler...

  1. Set e.Result = e.Argument (or create an object that will return both the argument and your desired result)

In the RunWorkerCompleted event hanlder...

  1. Remove the row identifier from the running processes list (e.Result is the identifier).
  2. Change the button text from "Running..." to "Ready"
Austin Salonen
Thanks for an interesting alternative, but I'd rather stick with the standard visual cue of graying out the buttons.
Don Kirkby