Click here to Skip to main content

Custom DataGrid with Progress Bar control

<!-- Article image -->

Sample Image - screen1.jpg

<!-- Add the rest of your HTML here -->

Introduction
Overview
The custom control
The control properties
Using the control
Conclusion

Introduction

When I saw a Microsoft's sample for using SQLXML that demonstrate a little project management application I said to myself, "It would be cool to have a similar progress control functionality in the dataset directly.". I work with data a lot and sometimes there are data items that are of a percentage type, that represent some progress#. It is very effective to show such data in a graphical way.

Overview

What we have here is a little sample of how to do such thing. It is a sample of how to create a custom control derived from the System.Windows.Forms.DataGrid object, and how to write custom property modify dialog. The Component allows the consumer to specify which columns are of the progress type within the grid, and the grid then renders the progress based upon specified attributes given to the grid object (like the color or style of the progress control).

The custom control

The project for the custom control itself is a standard C# Custom Control project. When creating it I just set up the new project from the custom project template.

The whole component implementation is done in one file - CProgressDataGrid.cs in the CProgressControls namespace (I thought that maybe it can be usefull to create more similar controls and put them under the same namespace.)

As you can see from the source, the class is separated into several areas, the functional API of the component to access the attributes programatically (via functionz or properties), - the region named 'accessor functions', and the main part, implemented in the region named 'painting functions'. This region contains the main OnPaint handler. The logic is very straightforward, get the list of columns that are marked as progress column types and then for every cell in such column, get its value and draw the box there. Simple as that.

Properties

There are some properties you can set up into the control, via Visual Studio's designer or via the component's API:

  • Color of the progress bar
  • Color of the progress bar percentage text
  • Flag if the percentage text is set to be shown or not
  • Style of the progress (can be 3D, flat, inset or with solid border)
  • Table name within the data set to use for populating the data
  • List of columns

There is the custom dialog used to select the columns for the progress control.

The custom property dialog

To implement your own property dialog you need to undertake several steps. First you need to create your own new value editor class. In this case it is CProgressDataGridColumnsValueEditor, as you can see it is derived from the UITypeEditor class. Basically you need to override two functions - GetEditStyle and EditValue. The GetEditStyle function is called from the VS.NET framework to retrieve the information about the type of the editor used for the property, there are 3 types defined - Modal, DropDown and None, for exact description see the documentation for the UITypeEditorEditStyle class.

In our case we use UITypeEditorEditStyle.Modal type. If you look at the EditValue function, you can see that this is very simple too. You can get the instance of the container if you wish, just type the context.Instance to your control's type. Here we have function call like:

CProgressDataGrid oGrid = (CProgressDataGrid)context.Instance;

On the next lines we create an instance of our dialog used to populate the list of columns. I will not go into description of the form used to do that (called CProgressDataGridColumnsValueEditorForm), it is not important for this sample, but the source is included so you can observe that part of code as well.

Once the property dialog ends it returns control to the EditValue function, it is recommended to store the information if the data was changed in the dialog and check it here, if this is the case then just copy the data to the value variable and return it so the value will be stored in the property.

I had a collection of type ArrayList that held the columns selected as progress bar columns, but whenever the persistent data was loaded from the resource file, the deserialization process went wrong. I tried to find a solution, but finally gave up, once I have some more time I'll dig into that again, of course if you have any ideas how to make a collection as a property persistent and updatable via the VS.NET designer, drop me a message. Anyway, in the end I decided to do it with a little trick. The list is stored in the string property, where the column indexes are delimited by the comma (,) separator, there is a little helper function that turns the string into the ArrayList object.

Using the control

So, "How can I use that" you migh ask. First place the built assembly, or the source, onto your machine and build it (in the case of the source). Once this is done, go into the Toolbox window and right click when you have some form selected, choose the "Customize toolbox" menu item and add the reference to this assembly. At the end of the component's list you will see the CProgressDataGrid, place it onto your form.

Control's properties

Then you need to specify a table style, and add some columns to the style according to the your underlaying dataset. Then you can scroll down and find the property group "Progress control", and specify the required color and type, whether you want to see the text or not, and the Table name within the data set. Once you have done this then click the "..." in the ProgressColumns attribute and use the dialog to select your "progress" columns. Save the project and build it.

That's it, if you have proper dataset bound to the data grid with some numerical data for the progress column you have chosen, then you should see the progress bars in that column.

Conclusion

Advantages

  • Simple
  • Easy to use
  • Several styles to choose from
  • Compact code

Limitations

  • No sorting support
  • No column reorder support
  • Selected columns property is not implemented as a collection
  • Support for only one table within the data set

Future possible extensions, ideas

  • Sorting support
  • More styles
  • In-place graphical editor (like the progress drag control in MS Project)
  • Style based per cell (column) not per grid only (every cell can have different progress)
  • Turn it into the new grid cell object? (like DataGridBoolColumn)

Web02 | 2.8.160208.1 | Advertise | Privacy
Copyright © CodeProject, 1999-2016
All Rights Reserved. Terms of Service