Browse DevX
Sign up for e-mail newsletters from DevX


The Baker's Dozen: 13 Productivity Tips for the Windows Forms DataGrid : Page 3

New developers often struggle with the .NET DataGrid when trying to replicate grid functionality from other platforms, while more experienced developers lament the deficiencies of the .NET DataGrid to address end user requirements. These tips will help both newbies and proficient developers work with the DataGrid.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Tips 3 and 4: Implementing Find/Find Next
When the application presents the user with a result DataSet in a grid, the data could be a handful of rows, or maybe a hundred, or maybe even more, depending on what condition was used to retrieve the data from the backend.

Many times, I look to Microsoft Word or Internet Explorer to get some ideas for user interface enhancements, and this was no exception.
Similar to Microsoft Word or other applications, the user may wish to locate a particular row by typing in search text, and clicking Find or Find Next if the first one wasn't the desired record. The user may also want to narrow the scope; maybe the row being searched is a deduction number that begins with 688, but the user doesn't want the software to return a match on other columns that might have 688 in them. Finally, the user may want to take the text search and turn it into a filter, perhaps to only show those deductions where the word SAFEWAY appears in the account name.

The grid Container class has a text search and command buttons for the Find/Find Next filter, all in the upper left corner. All you need to do to make these visible is to set a property in the container and call ShowGridTools:

oGridCtr.lShowGridTools = chkUseGridTools.Checked; oGridCtr.ShowGridTools();

If you don't wish to provide this functionality to users, set the property to False. The find and filter prompts disappear, and the grid automatically stretches vertically to cover the screen area.

Note the checkbox in the lower right corner of Figure 1, labeled "Use Search and Bookmark Tools." This demonstrates the use of the property lShowGridTools, as described above.

(Note that when turning on Grid Tools, you'll also see a bookmark drop-down on the right hand side. I'll cover that a little later in Tip 6.)

As for how the Find and Find Next filter works, the Ggrid class in ccControls.ccGrid contains a function called TextSearch. It takes two parameters: the text to search on, and a Boolean for whether to start at the top of the grid based on the current sort order (True), or whether to start at one row beyond the current row position in the grid (False).

The text searching is fairly basic. First, it starts at either the first row of the grid or the current position plus one (and I'll cover how it gets the current position when I cover the Binding Manager in Tip 8). Next, for each row, the search scans the columns from left to right, and checks whether or not the search text appears in the column.

cSearchText = cSearchText.ToUpper().Trim(); string cColValue; cColValue = this[nRowCtr,nColCtr].ToString().ToUpper(); if(cColValue.IndexOf(cSearchText,0)>=0) { lFound=true; break; } if(lFound==true) this.Select(nRowCtr);

Note that the search automatically converts both sides to upper case, making the search case-insensitive. Again, it also searches for partial occurrences within a string, using IndexOf(). Finally, note the use of the grid UnSelect() function, to unhighlight the row that was highlighted right before the search began (so that you can highlight the row that matches the search with the Select() function).

The code snippet above was an excerpt from FindText, where all columns were searched. As I mentioned, you can search only certain columns, if a user specifically wants to exclude a column or column from being searched.

At the time you executed the ShowGrid method, the grid Container class scanned through the grid class definition table, DtGridDef, read all the column headings passed with AddText, AddDropDown, and so on, and populated a CheckedListBox control with those headings. I like the CheckedListBox control because it provides an easy and graphical way for users to select multiple items when the total list of items isn't too large. By default, all heading boxes are checked. If the user wants to exclude columns from a search, he can just uncheck that column's name in the list.

When the user clicks Find or Find Next, the grid Container class reads through each item in the CheckedListBox, finds the corresponding column definition in DtGridDef, and sets the SEARCHCOLUMN flag in DtGridDef to either True or False. (With a little bit of additional work, the table DtGridDef could have been bound to the CheckedListBox control).

At the time of the actual text search when you are looping through the grid columns, if the user has only selected certain columns, you can check whether or not the column was defined as searchable before actually trying the search. To do so, first identify the column name for the current column in the loop. You get this by tapping into the grid's GridColumnStyles array and then examining the mapping name:

DataGridColumnStyle oCol; oCol = this.TableStyles[0].GridColumnStyles[nColCtr]; string cColumnName = oCol.MappingName.ToString();

Then look up the column name in DtGridDef and verify whether the SEARCH flag is set to True.

DataRow DrColumn; DrColumn = this.DtGridDef.Rows.Find(cColumnName); bool lSearch; lSearch = bool.Parse(DrColumn["Search"].ToString()); if(lSearch==true) // continue with search if(cColValue.IndexOf(cSearchText,0)>=0)

Finally, you may wish to filter on all rows in the grid that match the text search. The Filter button on the grid container calls a function in the grid class called SetTextFilter(). This function performs the same logic as the text search logic, except that for each row where a hit occurs, the function sets a flag in the grid's DataSource called FilterSelected to True. At the end, the function sets a RowFilter for the grid's DataSource to only show those rows where FilterSelected was set to True.

this.dvGrid.DefaultView[nRowCtr] ["filterselected"] = lFoundMatch; this.dvGrid.DefaultView.RowFilter = "FilterSelected = true";

Note the use of the property dvGrid. This is a custom property for the grid class. (All custom properties and methods are shown in Table 3. Because the grid has no way of knowing the name of the DataSource, you use the custom property dvGrid to refer to the default DataView of the grid.

Table 3: Exposed properties and functions for Grid Container (ccContainers.GridContainer).

Container Properties/Functions


String CcolumnToBookMa rk

Property for the column name to be bookmarked

Bool LsearchInColumns

Property for whether the user should be allowed to scope a text search to specific columns

Bool LshowGridTools

Property for whether the text search and bookmark options should appear (if set to False, the grid expands to cover the entire container)

ArrayList aBookMarks

ArrayList of the rows that have been bookmarked

Void SetupBookMark()

Sets the name of the column to be displayed in the bookmark drop-down. Pass the name of the column as a string.

Void ShowGridTools()

Displays the grid and grid search tools according to how lShowGridTools and lSearchInColumns are set, as well as whether a bookmark is defined

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date