Objective Grid for Microsoft .NET is a wrapper over the Objective Grid MFC libraries. It is easy to customize the libraries to implement the functionality you need. This section provides several examples of customization.
You can customize the behavior of your applications in a number of ways. This section includes some examples.
You can limit the data in a cell to accept only numeric data. For example:
this.gridControl1.ModifyCell += new Stingray.Grid.ModifyCellEventHandler(this.gridControl1_ModifyCell); private void gridControl1_ModifyCell(object sender, Stingray.Grid.ModifyCellEventArgs e) { string strValue = gridControl1[e.Row,e.Col].Style.Value; string strText = gridControl1[e.Row,e.Col].ControlText; if(!IsNumber(strText)) gridControl1[e.Row,e.Col].Style.Value = strValue; else gridControl1[e.Row,e.Col].Style.Value = strText; } //this function is from http://www.c-sharpcorner.com/3/RegExpPSD.asp private bool IsNumber(String strNumber) { Regex objNotNumberPattern=new Regex("[ˆ0-9.-]"); Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*"); Regex objTwoMinusPattern=new Regex("[0-9]*[-][0-9]*[-][0-9]*"); String strValidRealPattern="ˆ([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$"; String strValidIntegerPattern="ˆ([-]|[0-9])[0-9]*$"; Regex objNumberPattern =new Regex("(" + strValidRealPattern +") |(" + strValidIntegerPattern + ")"); return !objNotNumberPattern.IsMatch(strNumber) && objTwoDotPattern.IsMatch(strNumber) && objTwoMinusPattern.IsMatch(strNumber) && objNumberPattern.IsMatch(strNumber); } |
To highlight the value in a cell, add the following function to the file GridControl.h:
void SetSel(int nStartChar, int nEndChar); |
In the source file GridControl.cpp, add:
void GridControl::SetSel(int nStartChar, int nEndChar) { ROWCOL nCurRow, nCurCol; m_pCtrl->GetCurrentCell(&nCurRow, &nCurCol); if (m_pCtrl->GetCurrentCellControl()-> IsKindOf(RUNTIME_CLASS( CGXEditControl))) if (((CGXEditControl*)m_pCtrl->GetCurrentCellControl())->OnStartEditing()) { ((CGXEditControl*)m_pCtrl->GetCurrentCellControl())-> SetActive(TRUE); ((CGXEditControl*)m_pCtrl->GetCurrentCellControl())-> SetSel(nStartChar,nEndChar); ((CGXEditControl*)m_pCtrl->GetCurrentCellControl())->Refresh(); } } |
After rebuilding the assemblies, you can use code similar to the following:
gridControl1[2,2].Style.Value = "Hello"; gridControl1.CurrentCell = gridControl1[2,2]; gridControl1.SetSel(1,3); |
To advance a cursor from the last column in one row, to the first column of the next when the user presses either the right arrow, enter, or tab key, you can create a custom event handler. For example:
this.gridControl1.ProcessKeys += new Stingray.Grid.ProcessKeysEventHandler (this.gridControl1_ProcessKeys); private void gridControl1_ProcessKeys(object sender, Stingray.Grid.ProcessKeysEventArgs e) { if(( e.Char == 39 || e.Char == 9 || e.Char == 13) && e.Message == 256 && gridControl1.CurrentCell.Col == gridControl1.ColCount) { int col = gridControl1.CurrentCell.Col; int row = gridControl1.CurrentCell.Row; gridControl1.LockUpdate(); if(gridControl1.MoveCurrentCell(Stingray.Grid.DirectionType.Down)) { gridControl1.LockUpdate(false); gridControl1.MoveCurrentCell( Stingray.Grid.DirectionType.MostLeft); gridControl1.RedrawRowCol(row,col); e.Handled = true; } else gridControl1.LockUpdate(false); } } |
In most cases, the above works. However, when a cell is a combo box (for instance, style.Control = ControlType.DropDownList;), the enter/tab/left arrow/right arrow keys won't advance to the next row. Here is a workaround:
protected override System.Boolean ProcessCmdKey (ref Message m , Keys keyData ) { if(keyData == Keys.Tab || keyData == Keys.Enter || keyData == Keys.Right &&gridControl1.CurrentCell.Style.Control == ControlType.DropDownList) { bool bRight = gridControl1.MoveCurrentCell( Stingray.Grid.DirectionType.Right); if(bRight) return true; if(!bRight && gridControl1.CurrentCell.Col == gridControl1.ColCount) { int col = gridControl1.CurrentCell.Col; int row = gridControl1.CurrentCell.Row; gridControl1.LockUpdate(); if(gridControl1.MoveCurrentCell(Stingray.Grid.DirectionType.Down)) { gridControl1.LockUpdate(false); gridControl1.MoveCurrentCell(Stingray.Grid.DirectionType.MostLeft); gridControl1.RedrawRowCol(row,col); gridControl1.RedrawRowCol(row-1,col); return true; } gridControl1.LockUpdate(false); } } return base.ProcessCmdKey(ref m, keyData); } |
You can extend the last column to infinity during horitontal scrolling using this code:
private void gridControl1_HorizontalScroll(object sender, System.Windows.Forms.ScrollEventArgs e) { int nColCount = gridControl1.ColCount; Rectangle GridRect = gridControl1.GetGridRect(); int nRight = gridControl1.CalcRectFromRowColEx(1,nColCount).Right; gridControl1.SetColWidth(nColCount,nColCount, gridControl1.GetColWidth(nColCount)+ GridRect.Right-nRight); } |
Here is an example for setting the Max and Min date values in a DateTime control:
Style style = new Style(); style.Control = Stingray.Grid.ControlType.DateTime; style.set_UserAttribute(UserAttributeID.DATEMIN,"1/1/2000"); style.set_UserAttribute(UserAttributeID.DATEMAX,"1/1/2005"); style.set_UserAttribute(UserAttributeID.DATEVALIDMODE,"2"); gridControl1.SetStyleRange(Range.Cell(1,1),style); |
To deactivate the current cell in MFC version of Grid, we can use the following:
SetCurrentCell(GX_INVALID, GX_INVALID); |
We can implement the same feature in Grid for .NET, changing the source code in file gridcontrol.h:
[ Browsable(false) ] __property Stingray::Grid::Cell *get_Cell(Int32 nR, Int32 nC) { if(!(nR == -1 && nC == -1)) validateRowCol(nR, nC); return new Stingray::Grid::Cell(nR, nC, this, m_pCtrl); } |
After rebuilding the libraries, you can use the following in your program code:
gridControl1.CurrentCell = gridControl1[-1,-1]; |
You can use the function GetValueRowCol() to return the date from a cell with a DateTime control, rather than retrieving just the numeric value.
For example, the following function returns a System.DateTime object:
private DateTime GetDateFromCell(int nRow, int nCol) { string Value = gridControl1.GetValueRowCol(nRow,nCol); DateTime celldt; if(Value !="") { int nValue = Convert.ToInt32(Value); DateTime initdt = new DateTime(1899,12,30,12,0,0); TimeSpan ts = new TimeSpan(nValue,0,0,0); return celldt = initdt + ts; } else return celldt = DateTime.Today; } |
When tabbing through all the controls on a Windows Form, the Grid Control may not receive focus (i.e. may be skipped) even though the Grid Control's TabIndex and TabStop properties are set correctly. The following source code works around this issue in the Windows Form application. All changes below refer to the application's Windows Form *.cs file containing the Grid Control along with other .NET controls.
In the System.Windows.Forms.Form derived, public class, add the following private, initialized boolean variable:
private bool bEnableGridTabFocus = false; |
In the Windows Form Designer generated class private function InitializeComponent(), under the Grid Control section add the following event handler:
this.gridControl1.ProcessKeys += new Stingray.Grid.ProcessKeysEventHandler( this.gridControl1_ProcessKeys); |
After the Windows Form Designer generated class region, add the following protected override and private delegate:
protected override System.Boolean ProcessCmdKey(ref Message m, Keys keyData) { if (keyData == Keys.Tab || (keyData == (Keys.Shift | Keys.Tab))) { if (this.GetNextControl(Control.FromHandle(m.HWnd), true) == gridControl1) { bEnableGridTabFocus = true; return gridControl1.Focus(); } } return base.ProcessCmdKey(ref m, keyData); } private void gridControl1_ProcessKeys(object sender, Stingray.Grid.ProcessKeysEventArgs e) { if ((e.Char == 9 || e.Char == 65536) && !bEnableGridTabFocus) { GetNextControl(gridControl1, true).Focus(); e.Handled = true; } else if (bEnableGridTabFocus) bEnableGridTabFocus = false; } |
Rebuild the application to test the tab and shift+tab traversal and focus of each indexed control on the Windows Form.
To extract characters from a cell within a Virtual Grid, add a Cut event handler within the Grid Control as shown below:
this.gridControl1.Cut += new Stingray.Grid.CutEventHandler(this.gridControl1_Cut); private void gridControl1_Cut (object sender,System.EventArgs e) { gridControl1.SetSel(0,-1); } |
For information on the setSel() function, see Section 3.7.1.2, "Highlighting a Value in a Cell."
You can load OGL files in an application that uses the Objective Grid for Microsoft .NET component, like so:
private void InitializeComponent() { //fix for OGL this.gridControl1 = new Stingray.Grid.GridControl("..\\..\\Layout1.OGL"); ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); this.SuspendLayout(); // // gridControl1 // this.gridControl1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right); this.gridControl1.AutoScroll = true; this.gridControl1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; //fix for OGL this.gridControl1.FloatCells = Stingray.Grid.FloatCellsMode.EvalOnDisplay; this.gridControl1.EnableUndo = true; this.gridControl1.Size = new System.Drawing.Size(544, 408); this.gridControl1.TabIndex = 0; // // GridDocument // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(544, 413); this.Controls.AddRange(new System.Windows.Forms.Control[] {this.gridControl1}); ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); this.ResumeLayout(false); } |
This feature is implemented in <stingray-installdir>\Objective Grid for Microsoft .NET\Tutorials\1stGrid\Step 2.
This section discusses ways in which you can customize how your application is displayed to users.
You can display ellipses if the text in a column is greater than the column's width. To enable the use of ellipses:
Set the EllipseType in Properties\Current Cell\Style
Set WrapText to FALSE.
For example:
private void gridControl1_GridInitialized(object sender, System.EventArgs e) { Style style = new Style(); style.Value = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; style.WrapText = false; style.EllipseType = EllipseType.PoundEllipse; Range range = Range.Rows(2,5); gridControl1.SetStyleRange(range,style); } |
For very wide grids in which right-hand columns are not fully displayed, default Objective Grid for Microsoft .NET behavior is to shift the entire grid to the left when a user clicks in a far right-hand column, in order to allow its display.
You can disable this behavior by returning FALSE in CGXDynRegularGrid<T>::ScrollCellInView, like this:
template<class T> BOOL CGXDynRegularGrid<T>::ScrollCellInView(ROWCOL nRow, ROWCOL nCol, UINT flags /*= GX_UPDATENOW*/, BOOL bFloatCell /*= FALSE*/) { //return (m_bShowHierarchy == FALSE) ? //T::ScrollCellInView(nRow, nCol, flags, bFloatCell) : //CGXExRegularGrid<T>::ScrollCellInView(nRow, nCol, flags, bFloatCell); return FALSE; } |
Finally, rebuild GridControl.
By default, the style.control DateTime displays only the date, but you can also easily display the time. The format of the DateTime control is set by the UserAttribute (see the GridApp sample provided for an MFC Grid) as in the following code snippet:
private void gridControl1_GridInitialized(object sender, System.EventArgs e) { Style s = new Style(); s.Control = Stingray.Grid.ControlType.DateTime; s.set_UserAttribute(Stingray.Grid .UserAttributeID.CUSTOMFORMAT, "hh:mm"); s.Value = DateTime.Today.ToString(); gridControl1[1,1].Style = s; } |
To change the color of a cell's top border, edit the code in the file Stingray Studio\Objective Grid for Microsoft.NET\Solutions\GridControl\Style\Style.h, to add the code block between the comments, like this:
__property virtual void set_Borders( CellBorders *value ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if (value->IsAllBordersSame()) { cgxStyle_->SetBorders(gxBorderAll, Stingray::Grid::_marshal::CGXPen(value->Left)); } else { cgxStyle_->SetBorders(gxBorderLeft, Stingray::Grid::_marshal::CGXPen(value->Left)); cgxStyle_->SetBorders(gxBorderTop, Stingray::Grid::_marshal::CGXPen(value->Top)); cgxStyle_->SetBorders(gxBorderRight, Stingray::Grid::_marshal::CGXPen(value->Right)); cgxStyle_->SetBorders(gxBorderBottom, Stingray::Grid::_marshal::CGXPen(value->Bottom)); } } } //////////////// insert this code block ///////////////// else if (value->Left == NULL || value->Top==NULL || value->Right == NULL ||value->Bottom == NULL) { if (value->Left !=NULL) cgxStyle_->SetBorders(gxBorderLeft, Stingray::Grid::_marshal::CGXPen(value->Left)); else if (value->Top!=NULL) cgxStyle_->SetBorders(gxBorderTop, Stingray::Grid::_marshal::CGXPen(value->Top)); else if (value->Right != NULL) cgxStyle_->SetBorders(gxBorderRight, Stingray::Grid::_marshal::CGXPen(value->Right)); else if (value->Bottom !=NULL) cgxStyle_->SetBorders(gxBorderBottom, Stingray::Grid::_marshal::CGXPen(value->Bottom)); } ///////////////////////////////////////////////////////////// else { cgxStyle_->SetBorders(gxBorderLeft, Stingray::Grid::_marshal::CGXPen(value->Left)); cgxStyle_->SetBorders(gxBorderTop, Stingray::Grid::_marshal::CGXPen(value->Top)); cgxStyle_->SetBorders(gxBorderRight, Stingray::Grid::_marshal::CGXPen(value->Right)); cgxStyle_->SetBorders(gxBorderBottom, Stingray::Grid::_marshal::CGXPen(value->Bottom)); } } |
After rebuilding the assemblies, you can do the following:
gridControl1[e.Row, e.Col].Style.Borders = new Stingray.Grid.CellBorders( null,null,null, new Stingray.Grid.OGPen(BorderDashStyle.Dot, Color.Yellow, 1)); |
Set an interior color for a button control like this:
Style s = new Style(); s.Control = ControlType.Button; s.ChoiceList = "Set Color"; s.set_UserAttribute(UserAttributeID.BUTTONFACECOLOR, ColorTranslator.ToWin32(Color.White).ToString()); gridControl1.SetStyleRange(Range.Cell(3,1),s,CellModifyType.Override); |
To prevent the user from resizing hidden columns, use code like this:
private void gridControl1_StoreHideCol(object sender, Stingray.Grid.StoreHideColEventArgs e) { if(gridControl1.IsColHidden(e.Col)&& !e.Hide) e.Hide = true; } |
To set the font in a range of cells to bold:
Style style = new Style(); style.TextFont = new OGFont("Arial", 10, 0, true,false,false,false); gridControl1.SetStyleRange(Range.Cols(2,3), style); |
If you wish to make combobox button visible in inactive cell, add this code to the file GridControl.h:
public: void SetComboButtonVisible (int ID, bool Visible) and in file GridControl.cpp void GridControl::SetComboButtonVisible (int ID, bool bVisible) { ((CGXComboBoxWnd*)m_pCtrl->GetRegisteredControl(ID)) -> m_bInactiveDrawButton = bVisible; } |
After rebuilding the assemblies, you can use this code like so:
gridControl1.SetComboButtonVisible( GX_IDS_CTRL_CBS_DROPDOWN, true); |
UserAttributeIDs are enumeration types that marshall the MFC Grid style types used by the Objective Grid for Microsoft .NET grid control for the formatting of numeric cells.
The Objective Grid for Microsoft .NET UserAttributeIDs can be found in <stingray-install-dir>\Objective Grid for Microsoft .NET\Solutions\GridControl\Constants\OGEnumsAndConstants.h.
The marshalling of these enumeration types can be found in <stingray-install-dir>\Objective Grid for Microsoft .NET\Solutions\GridControl\Style\Style.h and Style.cpp.
Objective Grid for Microsoft .NET control provides a Currency control, Stingray.Grid.ControlType.Currency, which is flexible and easy to use.
Below are explanations and usage examples of some of these .NET UserAttributeIDs as used by the Grid Control's Currency control. Each item contains code snippets from the larger code block below illustrating the use of UserAttributeIDs to format numeric cells in various ways.
The comments in the larger code block reference the code snippet by item number for readability and ease of use.
private void Form1_Load(object sender, System.EventArgs e) { Style NumStyle = new Style(); NumStyle.Control = Stingray.Grid.ControlType.Currency; // See #1, "UserAttributeID.CURUMDECIMALS: Setting the Number // of Decimal Places for Numbers." NumStyle.set_UserAttribute(UserAttributeID.CURNUMDECIMALS,"4"); // See #2, "UserAttributeID.CURNEGFORMAT: Changing // the Display of Negative Numeric Values." NumStyle.set_UserAttribute(UserAttributeID.CURNEGFORMAT, "4"); // See #3, "UserAttributeID.CURSEP:Setting the Thousand // Separator Delimiter Character." NumStyle.set_UserAttribute(UserAttributeID.CURSEP,",."); // See #4, "UserAttributeID.CURMON: Constraining the Input // of Valid Numeric Data Only." NumStyle.set_UserAttribute(UserAttributeID.CURMON, "0"); gridControl2.SetStyleRange(Range.Cell(1,1),NumStyle); // See #1, "Required Event Handlers." gridControl2[1,1].Style.set_UserAttribute( UserAttributeID.CURNUMFRACT,"2"); gridControl2[1,1].Style.Value = "1234.1234"; } private void gridControl2_EndEditing(object sender, Stingray.Grid.EndEditingEventArgs e) { Style style = gridControl2[1,1].Style; // See #1, "Required Event Handlers." style.set_UserAttribute(UserAttributeID.CURNUMFRACT,"2"); gridControl2.SetStyleRange(Range.Cell(1,1), style); } private void gridControl2_StartEditing(object sender, Stingray.Grid.StartEditingEventArgs e) { Style style = gridControl2[1,1].Style; // See #1, "Required Event Handlers." style.set_UserAttribute(UserAttributeID.CURNUMFRACT,"4"); gridControl2.SetStyleRange(Range.Cell(1,1),style); } |
UserAttributeID.CURUMDECIMALS: Setting the Number of Decimal Places for Numbers
The end user should be able to change the number of decimal places at runtime.
For example, if the end user enters a value of 1000.00002 and the current format setting for the decimal place is set to 2, then the numeric value should be displayed as 1000.00, while the grid's cell maintains the actual value of 1000.00002.
NumStyle.set_UserAttribute(UserAttributeID.CURNUMDECIMALS,"4"); |
Required Event Handlers
Note that event handlers for Start and End editing are required for correct runtime behavior. These event handlers are implemented as shown:
. . . gridControl2[1,1].Style.set_UserAttribute( UserAttributeID.CURNUMFRACT,"2"); . . . } private void gridControl2_EndEditing(object sender, Stingray.Grid.EndEditingEventArgs e) { Style style = gridControl2[1,1].Style; style.set_UserAttribute(UserAttributeID.CURNUMFRACT,"2"); gridControl2.SetStyleRange(Range.Cell(1,1), style); } private void gridControl2_StartEditing(object sender, Stingray.Grid.StartEditingEventArgs e) { Style style = gridControl2[1,1].Style; style.set_UserAttribute(UserAttributeID.CURNUMFRACT,"4"); gridControl2.SetStyleRange(Range.Cell(1,1),style); } |
UserAttributeID.CURNEGFORMAT:Changing the Display of Negative Numeric Values
The end user should be able to change how negative numbers are displayed at runtime.
For example, if an end user enters -22.22, the numeric value should be displayed as (22.22), while the grid's cell maintains the actual value of -22.22.
NumStyle.set_UserAttribute(UserAttributeID.CURNEGFORMAT, "4"); |
UserAttributeID.CURSEP: Setting the Thousand Separator Delimiter Character
The end user should be able to change the number of decimal places at run time.
For example, if the end user enters a value of 10000, the numeric value should be displayed as 10,000, while the grid's cell maintains the actual value of 10000.
NumStyle.set_UserAttribute(UserAttributeID.CURSEP,",."); |
UserAttributeID.CURMON: Constraining the Input of Valid Numeric Data Only
The end user should be able to enter only valid numeric data in any given cell at runtime.
For example, the end user should be able to enter only numeric values in any given cell or range of cells with this attribute.
If the end user tries to enter some other non-numeric character, the cell should ignore that character.
NumStyle.set_UserAttribute(UserAttributeID.CURMON, "0"); |
Please refer to the section, UserAttributeID Enumeration, for a complete list of attributes and as listed in the Objective Grid for Microsoft® .NET® Reference Guide.
Please refer to the MFC Objective Grid's User's Guide and Reference Guide for details of the style types called from the MFC Objective Grid and marshalled by the Objective Grid for Microsoft .NET grid control.
You may change the background color of all cells in the grid. But to change the background color of the whole grid, so that the background color of the cells and the remaining area of the grid matches, you must make additional changes.
In the MFC Grid, use the following function:
CGXProperties::SetColor(int nIndex, COLORREF rgbColor) |
and then set nIndex, like this: nIndex = GX_COLOR_BACKGROUND.
In Objective Grid for Microsoft .NET, add the following code into public __gc class OGProperties in the OGProperties.h file, located in the ..\Solutions\GridControl\Param folder, as shown here:
__property void set_BkColor(Color value) { gxProp->SetColor(GX_COLOR_BACKGROUND,ColorTranslator::ToWin32(value)); } |
After rebuilding the assemblies, you can access this property from your C# code. After these changes, you can use the following code in your project:
this.gridControl1.BackColor = System.Drawing.Color.Azure; // cells this.gridControl1.Properties.BkColor = System.Drawing.Color.Azure; // out of cells |
This section describes how to set print margins and enable color printing.
In MFC Grid, use the following functions to set the print margins (left, right, top, bottom):
CGXProperties::SetDistances(int top, int bottom); CGXProperties::SetMargins(int top, int left, int bottom, int right); |
To set print margins with Objective Grid for Microsoft .NET using VC#, add the following code into public __gc class OGProperties in the OGProperties.h file, located in the ..\Solutions\GridControl\Param directory:
void SetDistances(int top, int bottom) { gxProp->SetDistances( top, bottom); } void SetMargins(int top, int left, int bottom, int right) { gxProp->SetMargins(top, left, bottom, right); } |
Rebuild the solution from the folder, ..\Solutions\GridControl. With the new assemblies, you will be able to call these functions in your project.
To enable/disable color printing for Objective Grid using VC#, add the following code into public __gc class OGProperties in the OGProperties.h file, located in the ..\Solutions\GridControl\Param directory:
__property void set_BlackWhite(bool b) { gxProp-> SetBlackWhite(BOOL b); } __property bool get_BlackWhite() { return gxProp->GetPrintBlackWhite(); } |
After rebuilding the assemblies, you will be able to access this property from your C# code.
Even if you are only displaying some cell grid lines, Objective Grid for Microsoft .NET may show grid lines for all cells in Print Preview and print them all as well. Exposing the following functions from the MFC base code to C# (similar to the approach demonstrated in Section 3.7.3.1) should resolve this problem:
CGXProperties::SetPrintHorzLines CGXProperties::SetPrintVertLines |
You can customize the behavior and display when sorting, discussed in this section.
You can mark the sorting column with a small triangle in the header, using the following code:
private void gridControl1_LButtonDblClkRowCol(object sender, Stingray.Grid.LButtonDblClkRowColEventArgs e) { if(e.Row ==0) { Style style = gridControl1[0,e.Col].Style; style.TextFont = new OGFont("Wingdings 3", 10, 0); style.Value = "q"; //"p"; style.TextColor = System.Drawing.Color.Blue; } } |
The code below sorts the values of a column when that column is double-clicked:
gridControl1.Param.EnableHorizontalSorting = true; gridControl1.Param.EnableVerticalSorting = false; |
For columns that lack a value in any row, you need to edit the code in the file gxDynRegularGrid.h and then rebuild the control, or attempts to sort the column result in a debug assert.
For example:
template<class T> void CGXDynRegularGrid<T>::OnGetSortRowsKey(ROWCOL nRow, const CGXSortInfoArray& sortInfo, CStringArray& keys) { m_bShowHierarchy == FALSE) ? T::OnGetSortRowsKey(nRow, sortInfo, keys) : CGXExRegularGrid<T>::OnGetSortRowsKey(nRow, sortInfo, keys); if(keys[0].IsEmpty()) keys[0] = _T("zzzzzz"); } |
This section provides tips and troubleshooting when dealing with memory or performance issues.
There are a few ways to set values in Objective Grid for Microsoft .NET: using property Style.Value or functions SetValueRange() and SetStyleRange(). The test in this section was used in the 1stGrid Tutorial sample to compare performance and speed for these methods.
Using LockUpdate(true) and LockUpdate(false) around the code of interest increases performance.
Add this code to the application's WinForm to perform benchmark testing:
private int nTicks; private void timer1_Tick(object sender, System.EventArgs e) { for(int nRow = 1; nRow<=10; nRow++) for(int nCol =1; nCol<=5; nCol++) gridControl1[nRow,nCol].Style.Value = nTicks.ToString(); nTicks++; } private void Form1_Load(object sender, System.EventArgs e) { this.timer1.Start(); this.timer1.Interval = 100; this.timer1.Tick += new EventHandler(timer1_Tick); } |
A menu option or button control may be added to the application's WinForm to perform benchmark tests.
For example, the button click event below was added to show how to benchmark test three different approaches when setting numeric values in the grid.
private void button1_Click(object sender, System.EventArgs e) { //gridControl1.LockUpdate(true); // Benchmark test of numbers set with Style.Value DateTime dtStart = DateTime.Now; for(int n =1; n <=1000; n++) { gridControl1[1,1].Style.Value = n.ToString(); } DateTime dtStop = DateTime.Now; TimeSpan duration = dtStop - dtStart; Console.WriteLine(duration); // Benchmark test of numbers set with SetValueRange() Style style = new Style(); dtStart = DateTime.Now; for(int n =1; n <=1000; n++) { style.Value = n.ToString(); gridControl1.SetValueRange(Range.Cell(1,1), style); } dtStop = DateTime.Now; duration = dtStop - dtStart; Console.WriteLine(duration); // Benchmark test of numbers set with SetStyleRange() dtStart = DateTime.Now; for(int n =1; n <=1000; n++) { style.Value = n.ToString(); gridControl1.SetStyleRange(Range.Cell(1,1), style); } dtStop = DateTime.Now; duration = dtStop - dtStart; Console.WriteLine(duration); //gridControl1.LockUpdate(false); } |
Test Results:
Benchmark test results without the use of LockUpdate(true) and LockUpdate(false):
00:00:01.6718750 // Duration of numbers set with Style.Value 00:00:01.5312500 // Duration of numbers set with SetValueRange() 00:00:01.5468750 // Duration of numbers set with SetStyleRange() |
Benchmark test results with the use of LockUpdate(true) and LockUpdate(false):
00:00:00.4218750 // Duration of numbers set with Style.Value 00:00:00.2968750 // Duration of numbers set with SetValueRange() 00:00:00.2812500 // Duration of numbers set with SetValueRange() |
This section includes possible issues you may encounter and methods for resolving them.
This section provides a workaround if an application appears to increase in memory usage.
Add these two two lines of code anywhere in your application where memory should be released.
HANDLE h = GetCurrentProcess(); SetProcessWorkingSetSize( h, -1, -1 ); |
A similar approach works with C#, where you can add this line at the top of the application's Form.cs file:
using System.Runtime.InteropServices; |
Then add this code block to the application's WinForm class, public class Form1 : System.Windows.Forms.Form:
[DllImport("kernel32.dll", SetLastError=true)] static extern int SetProcessWorkingSetSize ( int hProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize); [DllImport("kernel32.dll", SetLastError=true)] static extern int GetCurrentProcess(); |
Finally, call these two lines of code anywhere in your application where memory should be released.
int h = GetCurrentProcess(); SetProcessWorkingSetSize( h, -1, -1 ); |
Copyright © Rogue Wave Software, Inc. All Rights Reserved.
The Rogue Wave name and logo, and Stingray, are registered trademarks of Rogue Wave Software. All other trademarks are the property of their respective owners.
Provide feedback to Rogue Wave about its documentation.