How to change the row color that meets the specified condition in the DataGrid (winform)

Source: Internet
Author: User

 

I have the courage to post this post. I really don't know if anyone will read it. With the introduction of Whidbey, this problem should no longer exist-the new datagridview control is said to be able to directly set the row color-but considering that Whidbey is only a test version, the DataGrid control is still widely used, this article may be helpful to friends who face the same problem.

Everyone knows that the DataGrid Control controls the display style of each corresponding datatable through its tablestyles attribute, and each tablestyle controls the display style of each column through its gridcolumnstyles attribute, however, there is no property or method to directly set the display style of each row of data. This may be due to usage considerations (you certainly do not know which rows and what data exists in the rows before binding the data source ), it may be because of performance considerations (the cost of creating a display style index for each row is relatively high), or other considerations (I did not expect ^_^ ). However, in actual work, there are many such requirements, such as "Red when the resource is smaller than a critical value. If you can change the color of rows, most of these needs should be met. However, according to the conventional method, the display style of each cell (that is, each row) in a column is the same.

The basic technique for changing the row color of the DataGrid Control is to override the paint method of the datagridcolumnstyle, change the forebrush and backbrush parameters, and then re-call the painting method of the base class. Of course, in actual operations, we cannot directly inherit the datagridcolumnstyle class, but inherit from its subclass, datagridtextboxcolumn and datagridboolcolumn (unfortunately, we cannot insert our own class in this inheritance level, huh, huh ). As follows:
Public class datagridcoloredtextboxcolumn: datagridtextboxcolumn
{
// Reload the function used to draw a cell. If the row of the cell meets the coloredview conditions, the foreground and background color are changed.
Protected override void paint (system. Drawing. Graphics G,
System. Drawing. Rectangle bounds, system. Windows. Forms. currencymanager
Source, int rownum, system. Drawing. Brush backbrush, system. Drawing. Brush
Forebrush, bool aligntoright)
{
/* Add judgment conditions here to determine whether to change the color.
If (...)
Backbrush = new solid (...);
Forebrush = new solidbrush (...);
*/

// Call the base class plotting function
Base. Paint (G, bounds, source, rownum, backbrush, forebrush, aligntoright );
}
}

This method is easy to understand. We can add a public method to set the color for this class to specify the color when using it (here the color is a broad concept, for the brush, you can also specify the rendering method ). The key to the problem is how to set the condition in if: we can see that the rownum parameter of the paint method provides the row number being drawn, can I change the color of a row by specifying a row number? The answer is no. First, the row number given by rownum is the currently displayed row number, and we usually select the row number in datasource through some external conditions, because sorting and other operations will change the display order, the two may be inconsistent. Secondly, we often want to change the color of the rows that meet certain conditions, rather than the rows at a specific position. If the row number is specified directly, this will cause the color to become the background of the DataGrid.

In this case, can we use rownum to directly retrieve the content of the column to be determined, and determine whether to change color based on its value? Many examples on the Internet are implemented in this way. As a demonstration technique, it is enough, but it is not easy to use. This requires us to hard encode the judgment conditions ("age> 20", "name like 'jack'" and so on) in the method, which is not flexible enough, if different conditions need to be set in multiple places, isn't it necessary to write multiple classes? Besides, it is not so easy to obtain the value of a column corresponding to rownum.

To solve the above two problems, the ideal idea is to first find the corresponding row of rownum In the datasource to which it is bound, and then specify the row to be discolored through the public method, compare whether the two are equal. If they are equal, change the foreground and background according to the pre-set brush. The following is a method I found to get the row corresponding to rownum in datasource. It may not be concise enough to obtain a current dataview, but it is indeed available:
// Obtain the currently displayed dataview
Dataview currentview;
Type itype = This. datagridtablestyle. DataGrid. datasource. GetType ();
If (itype = typeof (system. Data. dataview ))
Currentview = (dataview) (This. datagridtablestyle. DataGrid. datasource );
Else if (itype = typeof (system. Data. datatable ))
Currentview = (datatable) (This. datagridtablestyle. DataGrid. datasource). defaultview;
Else if (itype = typeof (system. Data. dataset ))
Currentview = (Dataset) (This. datagridtablestyle. DataGrid. datasource). Tables [This. datagridtablestyle. mappingname]. defaultview;
Else if (itype = typeof (system. Data. dataviewmanager ))
{
Dataviewmanager ViewManager = (dataviewmanager) (This. datagridtablestyle. DataGrid. datasource );
Currentview = ViewManager. dataset. Tables [This. datagridtablestyle. mappingname]. defaultview;
}
Else
{// If datasource does not meet the preceding four types (it should not be correct), a system error is thrown.
Throw (New systemexception ());
}

// Retrieve the current row
Datarow currentrow = currentview [rownum]. row;

After finding the current row, you can compare it with a series of pre-specified rows to see if it should change color, as shown below:
// Search whether the current row is in the coloredview with the row Color Set
Datarow currentrow = currentview [rownum]. row;
Foreach (datarow coloredrow in m_coloreddatarows) // m_coloreddatarows is an array of the datarow type and a private member variable.
{
If (currentrow = coloredrow)
{
Backbrush = m_backbrush;
Forebrush = m_forebrush;
Break;
}
}
So far, we have finally given the conditions for determining if, and the problem is solved. For ease of use, we also provide a public method and several private members for the outside to set the row and color. This method can be roughly implemented as follows:
Private system. Data. datarow [] m_coloreddatarows;
Private system. Drawing. Brush m_forebrush;
Private system. Drawing. Brush m_backbrush;

// set the row color
Public void setrowscolor (datarow [] adatarows, system. drawing. brush aforebrush, system. drawing. brush abackbrush)
{< br> // set the row to change the color
m_coloreddatarows = adatarows;
// set the foreground color
m_forebrush = aforebrush;
// set the background color
m_backbrush = abackbrush;
}

the method of using this class is very simple. In the following example, dtable is a able object, and its select method is used to select the row to be discolored, as a real parameter of setrowscolor:
// set the column and the row style of each column
datagridtablestyle dgtablestyle = new datagridtablestyle ();
dgtablestyle. mappingname = dtable. tablename;
foreach (datacolumn eachcol in dtable. columns)
{< br> maid ();
dbcolumnstyle. mappingname = eachcol. c Olumnname;
// set the condition and foreground and background color of the color-changing row.
dbcolumnstyle. setrowscolor (dtable. select ("age> 20"), new solidbrush (color. white), new solidbrush (color. bluevilet);
dgtablestyle. gridcolumnstyles. add (dbcolumnstyle);
}< br>
// Add a style to datagrid1
datagrid1.tablestyles. add (dgtablestyle);
of course, if you want a stronger General type, this class still has many functions to be improved. For example, you can only set the color of one group of rows, setting again will replace the original content. To set the correspondence between multiple groups of rows and colors, you must add some data structures. In addition, you can only set the brush currently, so you cannot change the font or other functions. Yes, but I have not found any good method yet (neither the painting method nor the painttext method has any font parameters ).

Complete TestCodeAttached to the following:
Using system. Data;

Public class form2: system. Windows. Forms. Form
{
Public form2 ()
{
//
// Required for Windows Form Designer support
//
Initializecomponent ();

Datatable dtable;

// create a test able
dtable = new datatable ("person");
// Add a test column
dtable. columns. add (New datacolumn ("ID", typeof (INT);
dtable. columns. add (New datacolumn ("name", typeof (string);
dtable. columns. add (New datacolumn ("Age", typeof (INT);
// Add a test row
datarow newdatarow;
random irandom = new random ();
for (short I = 0; I <20; I ++)
{< br> newdatarow = dtable. newrow ();
newdatarow [0] = I;
newdatarow [1] = convert. tostring (irandom. next (0, 15) + "song";
newdatarow [2] = irandom. next (15,30);
dtable. rows. add (newdatarow);
}

// set the column and the row style of each column
datagridtablestyle dgtablestyle = new datagridtablestyle ();
dgtablestyle. mappingname = dtable. tablename;
foreach (datacolumn eachcol in dtable. columns)
{< br> maid ();
dbcolumnstyle. mappingname = eachcol. columnname;
// set the condition and foreground and background color of the color-changing row.
dbcolumnstyle. setrowscolor (dtable. select ("age> 20"), new solidbrush (color. white), new solidbrush (color. bluevilet);
dgtablestyle. gridcolumnstyles. add (dbcolumnstyle);
}< br>
// Add a style to datagrid1
datagrid1.tablestyles. add (dgtablestyle);
datagrid1.setdatabinding (dtable, "");
}< BR >}

Public class datagridcoloredtextboxcolumn: datagridtextboxcolumn
{
Private system. Data. datarow [] m_coloreddatarows;
Private system. Drawing. Brush m_forebrush;
Private system. Drawing. Brush m_backbrush;

// Set the row color
Public void setrowscolor (datarow [] adatarows, system. Drawing. Brush aforebrush, system. Drawing. Brush abackbrush)
{
// Set the row to change the color
M_coloreddatarows = adatarows;
// Set the foreground color
M_forebrush = aforebrush;
// Set the background color
M_backbrush = abackbrush;
}

// Reload the function used to draw a cell. If the row of the cell meets the coloredview conditions, the foreground and background color are changed.
Protected override void paint (system. Drawing. Graphics G,
System. Drawing. Rectangle bounds, system. Windows. Forms. currencymanager
Source, int rownum, system. Drawing. Brush backbrush, system. Drawing. Brush
Forebrush, bool aligntoright)
{
// Obtain the currently displayed dataview
Dataview currentview;
Type itype = This. datagridtablestyle. DataGrid. datasource. GetType ();
If (itype = typeof (system. Data. dataview ))
Currentview = (dataview) (This. datagridtablestyle. DataGrid. datasource );
Else if (itype = typeof (system. Data. datatable ))
Currentview = (datatable) (This. datagridtablestyle. DataGrid. datasource). defaultview;
Else if (itype = typeof (system. Data. dataset ))
Currentview = (Dataset) (This. datagridtablestyle. DataGrid. datasource). Tables [This. datagridtablestyle. mappingname]. defaultview;
Else if (itype = typeof (system. Data. dataviewmanager ))
{
Dataviewmanager ViewManager = (dataviewmanager) (This. datagridtablestyle. DataGrid. datasource );
Currentview = ViewManager. dataset. Tables [This. datagridtablestyle. mappingname]. defaultview;
}
Else
{// If datasource does not meet the preceding four types (it should not be correct), a system error is thrown.
Throw (New systemexception ());
}

// Search whether the current row is in the coloredview with the row Color Set
Datarow currentrow = currentview [rownum]. row;
Foreach (datarow coloredrow in m_coloreddatarows)
{
If (currentrow = coloredrow)
{
Backbrush = m_backbrush;
Forebrush = m_forebrush;
Break;
}
}

// Call the base class plotting function
Base. Paint (G, bounds, source, rownum, backbrush, forebrush, aligntoright );
}

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.