|
SourceGrid (http://www.devage.com/Wiki/ViewArticle.aspx?name=sourcegrid&version=0)
http://www.devage.com/
.NET Windows Forms grid control written entirely in C# with managed code. SourceGrid can be used to visualize or to change data in a table format.

Introduction SourceGrid is a .NET Windows Forms grid control written entirely in C# with managed code. SourceGrid can be used to visualize or to change data in a table format.
SourceGrid con be used bound to a data source (typically a DataView) or creating each cell directly.
There are a lot of controls of this type available, but often are expensive, difficult to customize or too DataSet oriented.
SourceGrid use only managed code (without API or Interop) and can be used with any .NET 2 compatible environments.
In this article I want to supply an overview of the utilization and functionalities of the SourceGrid control. For details on the classes, properties or methods you can consult the documentation in CHM format or the example project in the ZIP file.
For more information, a discussion forums, bug tracker system or to download the latest release go to the SourceForge page: http://sourceforge.net/projects/sourcegrid or to my home page http://www.devage.com/
Quick Start Installation To use SourceGrid you must have a .NET 2 compatible development environment (like Visual Studio 2005).
Download the latest release from http://sourceforge.net/projects/sourcegrid. Unzip the file and reference from your project these assemblies:
- SourceGrid.dll - SourceGrid core library
- DevAge.Core.dll - Helper library for common features
- DevAge.Windows.Forms.dll - Helper library for Windows Forms
- [SourceGrid.Extensions.dll - Optional library with some SourceGrid extensions like DataGrid, PlanningGrid]
Typically I suggest to always copy in the same location the *.xml files that you can find in the same directory of the assemblies to use the IDE IntelliSense features.
Open the form where you want to add the grid control, open the IDE ToolBox, right-click and select "Choose Items...". Browse and add SourceGrid.dll and SourceGrid.Extensions.dll assemblies on the IDE ToolBox.
These assemblies are the same assemblies required by the runtime that you must redistribute with your application to the end-user.
SourceGrid controls There are 2 main controls inside the SourceGrid.dll assembly:
- GridVirtual - A grid of virtual cells (ICellVirtual).
- Grid - A grid of real cells (ICell).
There are therefore two fundamentally distinct objects: virtual cells and real cells. Virtual cells are cells that determine the appearance and the behaviour of the cell but don't contain the value. The real cells have the same properties as virtual cells but also contain the value of the cell, and are therefore associated to a specific position in the grid.
You can use the Grid control for any kinds of grid where you don't need to display large amounts of cells (typically less than 50.000 cells). If you have to display large amount of cells you must usually use a GridVirtual derived controls, see the next chapters for more information.
Typically in this article I will use the Grid control because is more simply to use especially for simply examples. But consider that basically the same code can be used also for GridVirtual.
The Grid is also used if you have unusual grids that require maximum flexibility.
Drag the Grid control inside your forms as any other .NET control and start using it.
Basic examples For now SourceGrid has a poor design time support, so usually you must write manually the code to manipulate the grid.
Suppose that you have a Grid control named grid1 you can write this code in the Form.Load event:
grid1.BorderStyle = BorderStyle.FixedSingle;grid1.ColumnsCount = 3;grid1.FixedRows = 1;grid1.Rows.Insert(0);grid1[0,0] = new SourceGrid.Cells.ColumnHeader("String");grid1[0,1] = new SourceGrid.Cells.ColumnHeader("DateTime");grid1[0,2] = new SourceGrid.Cells.ColumnHeader("CheckBox");for (int r = 1; r < 10; r++){ grid1.Rows.Insert(r); grid1[r,0] = new SourceGrid.Cells.Cell("Hello " + r.ToString(), typeof(string)); grid1[r,1] = new SourceGrid.Cells.Cell(DateTime.Today, typeof(DateTime)); grid1[r,2] = new SourceGrid.Cells.CheckBox(null, true);}grid1.AutoSizeCells(); As you can see you can use the grid like a 2 dimension array. In the previous code I have set the grid border, the number of columns, the number of fixed rows and created the first header row. For the header I have used a ColumnHeader cell. With a simple loop I have created the other cells using a specific type for each column. The Cell class automatically creates an appropriate editor for the type specified (in this case a TextBox and a DateTimePicker). For the last column I have used a CheckBox cell that allows the display of a checkbox directly in the cell. Each kind of cell defines its own visual aspect and behaviour.
The form should look like the one in the following picture.
The grid created supports sorting, column sizing and editing of the cells.
Here some other important features:
- If you want to read or change the value of a cell you can use the grid1[r,c].Value property where r and c are the row and column of the cell.
- To remove a row you can write grid1.Rows.Remove(r)
- To change the width of a column you can write grid1.Columns[c].Width = 100
If you want to change some visual properties of the cell you must use the View class.
Let's see another example:
grid1.BorderStyle = BorderStyle.FixedSingle;grid1.ColumnsCount = 3;grid1.FixedRows = 1;grid1.Rows.Insert(0);SourceGrid.Cells.Views.ColumnHeader boldHeader = new SourceGrid.Cells.Views.ColumnHeader();boldHeader.Font = new Font(grid1.Font, FontStyle.Bold | FontStyle.Underline);SourceGrid.Cells.Views.Cell yellowView = new SourceGrid.Cells.Views.Cell();yellowView.BackColor = Color.Yellow;SourceGrid.Cells.Views.CheckBox yellowViewCheck = new SourceGrid.Cells.Views.CheckBox();yellowViewCheck.BackColor = Color.Yellow;grid1[0, 0] = new SourceGrid.Cells.ColumnHeader("String");grid1[0, 0].View = boldHeader;grid1[0, 1] = new SourceGrid.Cells.ColumnHeader("DateTime");grid1[0, 1].View = boldHeader;grid1[0, 2] = new SourceGrid.Cells.ColumnHeader("CheckBox");grid1[0, 2].View = boldHeader;for (int r = 1; r < 10; r++){ grid1.Rows.Insert(r); grid1[r, 0] = new SourceGrid.Cells.Cell("Hello " + r.ToString(), typeof(string)); grid1[r, 0].View = yellowView; grid1[r, 1] = new SourceGrid.Cells.Cell(DateTime.Today, typeof(DateTime)); grid1[r, 1].View = yellowView; grid1[r, 2] = new SourceGrid.Cells.CheckBox(null, true); grid1[r, 2].View = yellowViewCheck;} I have created a column header view with a style FontStyle.Bold | FontStyle.Underline, one view for a standard cell with a yellow backcolor and a checkbox view always with a yellow backcolor. Then I have assigned these instances to the View property of each cell.
The form should look like the one in the following picture.
You can note that I have assigned the same instance of the View class for many cells. This is useful to optimize the resources used.
Each cell can have an editor (Editor property) associated. The editor is used to edit the cell value. You can manually create an editor class (see SourceGrid.Cells.Editors namespace) or use the SourceGrid.Cells.Editors.Factory class to create an editor based on a Type. You can also use the Cell constructor that automatically calls SourceGrid.Cells.Editors.Factory if you specify the Type parameter.
Here an example that creates some cells and the editors associated using one of the methods described.
//A DateTime editorgrid1[r, c] = new SourceGrid.Cells.Cell(DateTime.Today, typeof(DateTime));//A string editorgrid1[r, c] = new SourceGrid.Cells.Cell("Ciao", typeof(string));//A double editorgrid1[r, c] = new SourceGrid.Cells.Cell(58.4);grid1[r, c].Editor = SourceGrid.Cells.Editors.Factory.Create(typeof(double)); Like the View classes also the editors can be shared between one or more cells.
Now you can start to work with SourceGrid, for more advanced information see the chapters below.
Basic Concepts Grid Control The Grid control is the ideal if you want the greatest flexibility and simplicity but without many cells. In fact, in this control every cell is represented by a .NET class and therefore occupies a specific quantity of resources. Moreover this is the only grid that supports features of RowSpan and ColumnSpan (cells merge).
Using the control in a Windows form is trivial. It's just like adding any other control like a Button or a DataGrid. First, create or open a Windows Application project and open a Windows Form into the designer. Now you are ready to customize the Toolbox: Right-Click the Toolbox, .NET Framework Components, Browse, select the DevAge.SourceGrid.dll. The Grid Control is now added to the Toolbox and can be inserted in Windows Form as any other control.
After inserting the control in the form we can begin to write our code using the grid. For example in the Load event of the form we can write this code:
grid1.Redim(2, 2);grid1[0,0] = new SourceGrid.Cells.Cell("Hello from Cell 0,0");grid1[1,0] = new SourceGrid.Cells.Cell("Hello from Cell 1,0");grid1[0,1] = new SourceGrid.Cells.Cell("Hello from Cell 0,1");grid1[1,1] = new SourceGrid.Cells.Cell("Hello from Cell 1,1");The previous code creates a table with 2 lines and 2 columns (Redim method) and populates every position with a cell. I have used the SourceGrid.Cells namespace which contains the definition for real cells.
To read a specific value of the grid you can use the value property of the cell like this: object val = grid1[1,0].Value;.
See the other chapters for more information.
GridVirtual Control The GridVirtual control is ideal when it is necessary to visualize a lot of cells and you already have available structured data like a DataSet, an Array, a document XML or other data structure.
This type of grid have the same features of the Grid control except for the automatic sort (this because the grid cannot automatically order any external data structure without copying its content) and the feature of RowSpan and ColumnSpan that allows spanning of a cell across other adjacent cells.
Another disadvantage is that creating a virtual grid is a little more difficult.
The main concept in a virtual grid is that each cell reads and writes its value from an external data structure and the grid doesn't maintain all the rows and columns but are normally read directly from the data source. This idea was implemented with an abstract GridVirtual class and with the abstract methods CreateRowsObject, CreateColumnsObject and GetCell. Then you can use a special IValueModel to read the values directly from the data source.
To use GridVirtual it is therefore necessary to create a class that derives from GridVirtual and personalize the reading of the data source overriding CreateRowsObject, CreateColumnsObject and GetCell methods.
The purpose of the method GetCell is to return, for a given position (row and column), the chosen cell, the methods CreateRowsObject and CreateColumnsObject are used to create the columns and the rows objects for the used data source. This allows great flexibility because you can return any ICellVirtual for a specific type; for example you could return a cell of type header when the row is 0.
Usually you don't need to use directly the GridVirtual but one of the derived controls. For now I have implemented two controls that directly use the virtual grid features:
- DataGrid - A grid bound to a DataView object.
- ArrayGrid - A grid bound to an Array object.
If you want to create your custom control to read from a specific data source you can see ArrayGrid class for an example.
Cell overview Every cell is composed of four fundamental parts based on a modified Model-View-Controller pattern:
- Model : The Model is the class that manages the value of the cells. It contains the values or properties associated and is accessible by the other components.
- View : The View is the class that draws the cell and contains the visual properties.
- Controller : The Controller is the class that supplies the behaviour of the cell.
- Editor : The Editor is the class used to customize the editor of the cell.
This subdivision grants great flexibility and reusability of code, saves time and supplies a solid base for every type of customization.
For the more common cases there are some classes already arranged and configured, but with a few lines of code is possible to create personalized cells (see the next paragraphs for the details).
Rows and Columns The main components of a grid are the rows and the columns. To manipulate this information, SourceGrid supplies 2 properties:
- Rows - Manages the rows information, the base class is the RowsBase class.
- Columns - Manages the columns information, the base class is the ColumnsBase class.
When using a real grid the base classes are extended with the RowInfoCollection and the ColumnInfoCollection. These are collection of RowInfo and ColumnInfo classes. When using a virtual grid you must extend the base classes with your custom code to provide information of your data source.
Manipulating Rows and Columns on real grid NOTE: Only valid for real grid.
These are some of the RowInfo class properties: Height, Top, Bottom, Index, Tag. In contrast, these are the properties of the ColumnInfo class:Width, Left, Right, Index, Tag.
There are many ways to create rows and columns:
- grid1.Redim(2,2);
- grid1.RowsCount = 2;grid1.ColumnsCount = 2;
- grid1.Rows.Insert(0);grid1.Rows.Insert(1);grid1.Columns.Insert(0);grid1.Columns.Insert(1);
These three examples perform all the same task of creating a table with 2 rows and 2 columns.
To change the width or the height of a row or a column you can use this code:
grid1.Rows[0].Height = 100;grid1.Columns[0].Width = 100;The properties Top, Bottom, Left and Right are automatically calculated using the width and the height of the rows and columns.
After allocating the rows and columns, you must create for each position of the grid the required cells, like this code:
grid1.Redim(2,2);grid1[0, 0] = new SourceGrid.Cells.Cell("Cell 0, 0");grid1[1, 0] = new SourceGrid.Cells.Cell("Cell 1, 0");grid1[0, 1] = new SourceGrid.Cells.Cell("Cell 0, 1");grid1[1, 1] = new SourceGrid.Cells.Cell("Cell 1, 1");Model Namespace: SourceGrid.Cells.Models
The purpose of the Model classes is to separate the data in the cells from the cell object. This separation is used for two main reasons:
- To implement virtual grid, where the values are stored only in the original data source. In this case the Model, if implemented in the right way, reads the data directly from the data source.
- To extend the cells classes but maintaining an easy reusability of the code. This is because you don't have to change the base Cell class to add new features, but you can simply add a new Model.
Every cell has a property Model that gets or sets a ModelContainer object. This class is a collection of IModel interface. Each IModel interface contains all the properties used for a specific feature.
The main Model is the ValueModel which contains the value of the cell, but there also other models and you can crate your custom models. Here are the default models:
- IValueModel
- IToolTipText
- ICheckBox
- ISortableHeader
Each of these models contains the properties specified for each features, for example the IToolTipText contains the ToolTipText string.
Each cell has a collection of models to allow using many features on a single cell.
Usually using real cell you can use a model that simply implement the right interface storing directly the required data; using virtual grid you can implement the interface to bind the values directly to an external data source.
View Namespace: SourceGrid.Cells.Views
Every cell has a property View to gets or sets an interface of type IView. The cell uses this interface to draw and to customize the visual properties of the cell.
The purpose of the View is to separate the drawing code from the rest of the code and allows sharing of the same visual properties between cells. In fact the same instance of View can be used on many cells simultaneously thus optimizing the use of the resources of the system.
These are the default View classes in the namespace SourceGrid.Cells.Views:
- SourceGrid.Cells.Views.Cell - Used for classic cells. In this view you can customize the colours, the font, the borders and a lot other properties.
- SourceGrid.Cells.Views.Button - Used for a cell with a button style with theme support.
- SourceGrid.Cells.Views.Link - Used for a cell with a link style.
- SourceGrid.Cells.Views.CheckBox* - Used for checkbox style cells. The checkbox can be selected, disabled and can contain a caption.
- SourceGrid.Cells.Views.Header* - Used for a generic header cell.
- SourceGrid.Cells.Views.ColumnHeader* - Used for a column header cell with theme support.
- SourceGrid.Cells.Views.RowHeader - Used for row header cell with theme support.
- SourceGrid.Cells.Views.MultiImages - Allows the drawing of more than one image in the cell.
*The View marked with an asterisk requires special components to work correctly, for example the CheckBox view needs an ICheckBoxModel.
Some of the previous classes contain one or more static properties with some convenient default instances.
This code shows how to create a View class, change some properties and assign it to more cells previously created:
SourceGrid.Cells.Views.Cell view = new SourceGrid.Cells.Views.Cell();view.BackColor = Color.Khaki;grid1[0,0].View = view;grid1[2,0].View = view;With some line of code you can create your custom View, in this case I suggest deriving your class from Cell, which already has implemented some default methods. In the following code example I create a View that draws a red ellipse over the cell:
public class MyView : SourceGrid.Cells.Views.Cell{ protected override void DrawCell_Background(SourceGrid.Cells.ICellVirtual p_Cell, SourceGrid.Position p_CellPosition, PaintEventArgs e, Rectangle p_ClientRectangle) { base.DrawCell_Background (p_Cell, p_CellPosition, e, p_ClientRectangle); e.Graphics.DrawEllipse(Pens.Red, p_ClientRectangle); }}To use this new View in a cell use this code:
MyView myView = new MyView();//...... code to populate the gridgrid1[r, c].View = myView;Controller Namespace: SourceGrid.Cells.Controllers
Every cell has a property Controller that gets or sets a ControllerContainer object. This class is a collection of IController interface. Each IController interface can be used to extend the behaviour of the cell using many events like Click, MouseDown, KeyPress, ...
These are the default classes:
- SourceGrid.Cells.Controllers.Cell - Common behaviour of a cell.
- SourceGrid.Cells.Controllers.Button - A cell that acts as a button.
- SourceGrid.Cells.Controllers.CheckBox* - A cell with a behaviour of a CheckBox. (need ICheckBox Model)
- SourceGrid.Cells.Controllers.ColumnFocus - Used to set the focus on the column when clicking the header cell.
- SourceGrid.Cells.Controllers.ColumnSelector - Used to set select the column when clicking the header cell.
- SourceGrid.Cells.Controllers.CustomEvents - Exposes a list of events that you can use without creating a new Controller.
- SourceGrid.Cells.Controllers.FullColumnSelection - Used to enable the columns selection mode.
- SourceGrid.Cells.Controllers.FullRowSelection - Used to enable the rows selection mode.
- SourceGrid.Cells.Controllers.MouseCursor - Used to display a mouse cursor over the cell.
- SourceGrid.Cells.Controllers.MouseInvalidate - Used to invalidate the cell area when receiving a mouse event.
- SourceGrid.Cells.Controllers.Resizable - Used to create a resizable cell, for both width and height.
- SourceGrid.Cells.Controllers.RowFocus - Used to set the focus on the row when clicking the header cell.
- SourceGrid.Cells.Controllers.RowSelector - Used to set select the row when clicking the header cell.
- SourceGrid.Cells.Controllers.SortableHeader* - Used to create a sortable column header cell. (need a ISortableHeader Model)
- SourceGrid.Cells.Controllers.ToolTipText* - Used to create a cell with a ToolTip. (need IToolTipText Model)
- SourceGrid.Cells.Controllers.Unselectable - Used to create an unselectable cell.
*The Controller marked with an asterisk need special models to complete their tasks.
Some of the previous classes contain one or more static properties with some convenient default instances.
Here the list of events that can be used inside a Controller:
- Mouse: OnMouseDown, OnMouseUp, OnMouseMove, OnMouseEnter, OnMouseLeave
- Keys: OnKeyUp, OnKeyDown, OnKeyPress
- Click: OnDoubleClick, OnClick
- Focus: OnFocusLeaving, OnFocusLeft, OnFocusEntering, OnFocusEntered, CanReceiveFocus
- Cell Value: OnValueChanging, OnValueChanged
- Edit: OnEditStarting, OnEditStarted, OnEditEnded
With some line of code you can create your custom Controller, in this case I suggest deriving your class from ControllerBase, which already have implemented some default methods. In the following code example I create a Controller that changes the backcolor of the cell when the user moves the mouse over it:
public class MyController : SourceGrid.Cells.Controllers.ControllerBase{ private SourceGrid.Cells.Views.Cell MouseEnterView = new SourceGrid.Cells.Views.Cell(); private SourceGrid.Cells.Views.Cell MouseLeaveView = new SourceGrid.Cells.Views.Cell(); public MyController() { MouseEnterView.BackColor = Color.Green; } public override void OnMouseEnter(SourceGrid.CellContext sender, EventArgs e) { base.OnMouseEnter (sender, e); sender.Cell.View = MouseEnterView; sender.Grid.InvalidateCell(sender.Position); } public override void OnMouseLeave(SourceGrid.CellContext sender, EventArgs e) { base.OnMouseLeave (sender, e); sender.Cell.View = MouseLeaveView; sender.Grid.InvalidateCell(sender.Position); }}To use this new Controller in a cell use this code:
MyController myController = new MyController();//...... code to populate the gridgrid1[r, c].AddController(myController);You can also add a controller to the whole grid to apply the same controller to all the cells:
grid1.Controller.AddController(new MyController());Consider for example the Controller below that open a messagebox each time a user click on a cell:
class ClickController : SourceGrid.Cells.Controllers.ControllerBase{ public override void OnClick(SourceGrid.CellContext sender, EventArgs e) { base.OnClick(sender, e); object val = sender.Value; if (val != null) MessageBox.Show(sender.Grid, val.ToString()); }} You can add this controller to all the cells with this code:
grid1.Controller.AddController(new ClickController());Here another example of how to use a controller to check when the value of a cell change, using the OnValueChanged event:
public class ValueChangedEvent : SourceGrid.Cells.Controllers.ControllerBase{ public override void OnValueChanged(SourceGrid.CellContext sender, EventArgs e) { base.OnValueChanged(sender, e); string val = "Value of cell {0} is '{1}'"; MessageBox.Show(sender.Grid, string.Format(val, sender.Position, sender.Value)); }} You can add this controller to all the cells with this code:
grid1.Controller.AddController(new ValueChangedEvent());Each time the value of a cell change the previous controller show a messagebox with the position of the cell and the new value.
Editor Namespace: SourceGrid.Cells.Editors
Every cell has a property Editor that gets or sets an EditorBase object. This class is used to supply a cell editor. If this property is null it is not possible to edit the cell.
Usually the Editor uses the Model class to manage the necessary conversion, particularly the string conversion (used to represent the cell value).
These are the default classes:
- ComboBox - A ComboBox editor.
- DateTimePicker - A DateTimePicker editor.
- NumericUpDown - A NumericUpDown editor.
- TextBox - A TextBox editor. This is one of the more used editors by all types that support string conversion (string, int, double, enum,....).
- TextBoxCurrency - A TextBox editor specialized for numeric currency values.
- TextBoxNumeric - A TextBox editor specialized for numeric values.
- TimePicker - A DateTimePicker editor specialized for time values.
- TextBoxUITypeEditor - Supplies the editing of the cell of all types that have a UITypeEditor. This is a very useful class because a lot of types support this class: DateTime, Font, enums, and you can also create your custom UITypeEditor.
- ImagePicker - An editor that can be used to select an image file and edit a byte[] values.
An Editor can be shared between many cells of the same grid; for example you can use the same Editor for every cell of a column, but always with the same grid.
Each Editor class has a property Control that returns an instance of the Windows Forms control used to edit the cell. You can use this instance to customize the editor control or for advanced features.
Here some ways to create an editable cell:
- Create the cell specifying the value type. In this way the cell automatically calls a utility function, SourceGrid.Cells.Editor.Factory.Create, which returns a valid Editor for the type specified or null. //String cellgrid1[0, 0] = new SourceGrid.Cells.Cell("Hello", typeof(string));//Double cellgrid1[0, 1] = new SourceGrid.Cells.Cell(0.7, typeof(double));
- Create the Editor separately and then assign it to the cells: //String editorSourceGrid.Cells.Editors.IEditor editorString = SourceGrid.Cells.Editor.Factory.Create(typeof(string));//Double editorSourceGrid.Cells.Editors.IEditor editorDouble = SourceGrid.Cells.Editor.Factory.Create(typeof(double));//String cellgrid1[0, 0] = new SourceGrid.Cells.Cell("Hello");grid1[0, 0].Editor = editorString;//Double cellgrid1[0, 1] = new SourceGrid.Cells.Cell(0.7);grid1[0, 1].Editor = editorDouble;This method is recommended when you want to use the same editor for several cells.
- Create manually the correct editor and then assign it to the cells: SourceGrid.Cells.Editors.TextBox txtBox = new SourceGrid.Cells.Editors.TextBox(typeof(string));grid1[2,0].Editor = txtBox;
If you need greater control on the type of editor or there are special requirements I suggest to manually creating the editor.
In this case, for example, I manually create the class EditorTextBox and then set the property MaxLength.
//String editorSourceGrid.Cells.Editors.TextBox editorString = new SourceGrid.Cells.Editors.TextBox(typeof(string));editorString.Control.MaxLength = 10;//String cellgrid1[0, 0] = new SourceGrid.Cells.Cell("Hello");grid1[0, 0].Editor = editorString;The editor can be used also to customize the format of the cell, in the code below for example I create a cell with a custom numeric format:
//Double editorSourceGrid.Cells.Editors.TextBoxNumeric editorDouble = new SourceGrid.Cells.Editors.TextBoxNumeric(typeof(double));editorDouble.TypeConverter = new DevAge.ComponentModel.Converter.NumberTypeConverter(typeof(double), "#,###.00");//String cellgrid1[0, 0] = new SourceGrid.Cells.Cell(9419.3894);grid1[0, 0].Editor = editorDouble;I have used the TypeConverter property to customize the conversion to and from string values. There are many other TypeConverter available:
- DevAge.ComponentModel.Converter.NumberTypeConverter - For numeric types like double, decimal, int, float
- DevAge.ComponentModel.Converter.PercentTypeConverter - For numeric types like double, decimal and float but with percent format.
- DevAge.ComponentModel.Converter.CurrencyTypeConverter - For Decimal and double types with currency format.
- DevAge.ComponentModel.Converter.DateTimeTypeConverter - For DateTime type.
Below another example that create a DateTime editor with a custom format:
//DateTime editor with custom formatstring[] dtParseFormats = new string[] { dtFormat2 };System.Globalization.DateTimeStyles dtStyles = System.Globalization.DateTimeStyles.AllowInnerWhite | System.Globalization.DateTimeStyles.AllowLeadingWhite | System.Globalization.DateTimeStyles.AllowTrailingWhite | System.Globalization.DateTimeStyles.AllowWhiteSpaces;TypeConverter dtConverter = new DevAge.ComponentModel.Converter.DateTimeTypeConverter(dtFormat2, dtParseFormats, dtStyles);SourceGrid.Cells.Editors.TextBoxUITypeEditor editorDt2 = new SourceGrid.Cells.Editors.TextBoxUITypeEditor(typeof(DateTime));editorDt2.TypeConverter = dtConverter;grid[currentRow, 1] = new SourceGrid.Cells.Cell(DateTime.Today);grid[currentRow, 1].Editor = editorDt2; The following picture shows most of the editors available and some special cells (picture from Sample 3):
It is possible to create a custom Editor with custom control or special behaviours with few lines of code.
You can derive your custom class from EditorControlBase and create any Windows Forms control. This is an example of an editor that uses DateTimePicker control:
public class DateTimePicker : EditorControlBase{ public DateTimePicker():base(typeof(System.DateTime)) { } protected override Control CreateControl() { System.Windows.Forms.DateTimePicker dtPicker = new System.Windows.Forms.DateTimePicker(); dtPicker.Format = DateTimePickerFormat.Short; dtPicker.ShowCheckBox = AllowNull; return dtPicker; } protected override void OnChanged(EventArgs e) { base.OnChanged(e); if (Control != null) Control.ShowCheckBox = AllowNull; } public new System.Windows.Forms.DateTimePicker Control { get { return (System.Windows.Forms.DateTimePicker)base.Control; } } protected override void OnStartingEdit(CellContext cellContext, Control editorControl) { base.OnStartingEdit(cellContext, editorControl); System.Windows.Forms.DateTimePicker dtPicker = (System.Windows.Forms.DateTimePicker)editorControl; dtPicker.Font = cellContext.Cell.View.Font; } public override void SetEditValue(object editValue) { if (editValue is DateTime) Control.Value = (DateTime)editValue; else if (editValue == null) Control.Checked = false; else throw new SourceGridException ("Invalid edit value, expected DateTime"); } public override object GetEditedValue() { if (Control.Checked) return Control.Value; else return null; } protected override void OnSendCharToEditor(char key) { }}Consider that you can share the same instance of the editor with many cells but only with a single grid control. Basically each editor is associated with only one grid.
For large grid it is always a good idea to share the editors, because each editor has a Windows Forms Control associated and so it is quite heavy.
Advanced cells Namespace: SourceGrid.Cells
These are the default cells available:
- SourceGrid.Cells.Virtual - This namespace contains all the virtual cells that can be used with a GridVirtual control.
- CellVirtual - Base cell for each other implementations; use for the most common type of virtual cells.
- Header - A header cell.
- ColumnHeader - A column header cell.
- RowHeader - A row header cell.
- Button - A button cell.
- CheckBox - A checkbox cell.
- ComboBox - A combobox cell.
- Link - A link style cell.
- Image - An image cell.
- SourceGrid.Cells - This namespace contains all the real cells that can be used with a Grid control.
- Cell - Base cell for all other implementations; use for the most common type of real cells.
- Header - A header cell.
- ColumnHeader - A column header cell.
- RowHeader - A row header cell.
- Button - A button cell.
- CheckBox - A checkbox cell.
- ComboBox - A combobox cell.
- Link - A link style cell.
- Image - An image cell.
The goal of these classes is to simplify the use of View, Model, Controller and Editor classes. If we look at the code of any of the cell classes we can see that these classes use these components according to the role of the cell.
This is, for example, the code of the cell SourceGrid.Cells.CheckBox:
public class CheckBox : Cell{ public CheckBox(string caption, bool checkValue):base(checkValue) { if (caption != null && caption.Length > 0) View = Views.CheckBox.MiddleLeftAlign; else View = Views.CheckBox.Default; Model.AddModel(new Models.CheckBox()); AddController(Controllers.CheckBox.Default); AddController(Controllers.MouseInvalidate.Default); Editor = new Editors.EditorBase(typeof(bool)); Caption = caption; } private Models.CheckBox CheckBoxModel { get{return (Models.CheckBox)Model.FindModel(typeof(Models.CheckBox));} } public bool Checked { get{return CheckBoxModel.GetCheckBoxStatus(this, Range.Start).Checked;} set{CheckBoxModel.SetCheckedValue(this, Range.Start, value);} } public string Caption { get{return CheckBoxModel.Caption;} set{CheckBoxModel.Caption = value;} }}Focus and Selection A cell can be selected or can have the focus. Only one cell can have the focus, identified by the Grid.Selection.ActivePosition property of the grid, while many cells can be selected. A cell is selected when is present in the Selection object of the grid.
The cell with the focus receives all the mouse and keyboard events, while the selected cells can receive actions like copy, paste and clear.
To set the focus on a specific cell you can use Grid.Selection.Focus(Position pos) method, using for input the position of the cell that will receive the focus, use Position.Empty as parameter to remove the focus.
Use the Grid.Selection.SelectCell method or SelectRange method to add or remove specific cells from the selection.
To list all the selected cells you can use Grid.Selection.GetRanges() method that returns a list of selected Range, or check if a particular cell is selected using the IsSelectedCell method. You can customize many aspects of the selection with these properties: Grid.Selection.BackColor, Grid.Selection.Border, Grid.Selection.FocusBackColor, ...
You can also use these events to respond to specific action of the user: Grid.Selection.FocusRowEntered, Grid.Selection.FocusRowLeaving, Grid.Selection.FocusColumnEntered, Grid.Selection.FocusColumnLeaving, Grid.Selection.CellLostFocus, Grid.Selection.CellGotFocus, Grid.Selection.SelectionChanged, ...
You can set the selection mode using the Grid.SelectionMode property. The available options are: GridSelectionMode.Cell, GridSelectionMode.Row and GridSelectionMode.Column. In this way you can set the grid to select only entire row, entire column or only single cell.
To enable or disable multi selection you must use the Grid.Selection.EnableMultiSelection property. You can select multiple cells using the mouse or with the Ctrl or Shift key.
Position and Range Two of the most used objects in the project are the structures Position and Range. The struct Position identifies a position with a Row and a Column, while the struct Range identifies a group of cells delimited from a start Position and an end Position.
You can read the actual location of a specified cell using grid.PositionToRectangle method. The resulting rectangle is relative to the grid client area. You can convert the resulting Rectangle to an absolute screen position using grid.PointToScreen.
You can obtain the Position for a specific client area Point using grid.PositionAtPoint method.
CellContextCellContext is a structure that encapsulates a Cell and a Position and contains all the method to manipulate the cells.
The most important methods are:
- StartEdit/EndEdit - To start/stop editing on a specified cell
- DisplayText - Returns the text of the cell (string)
- Value - Returns the value of the cell (object)
Here a common example that show how to use a CellContext class:
SourceGrid.CellContext context = new SourceGrid.CellContext(grid, new SourceGrid.Position(r, c));context.Value = "hello";context.StartEdit(); Usually a CellContext instance is automatically created as a parameter of the controller events, in this way you can always access the main cell properties.
Advanced Features Border Each View class has a property Border of type DevAge.Drawing.IBorder. The DevAge.Drawing.IBorder is a generic interface that can be used to draw a border around the cell.
Usually the IBorder interface it is implemented by the DevAge.Drawing.RectangleBorder structure.
Below an example to change a border of a cell:
DevAge.Drawing.Border border = new DevAge.Drawing.Border(Color.Red, 1);DevAge.Drawing.RectangleBorder cellBorder = new DevAge.Drawing.RectangleBorder(border, border);SourceGrid.Cells.Views.Cell view = new SourceGrid.Cells.Views.Cell();view.Border = cellBorder;grid[r, c].View = view; The default border set only the Right and Bottom side, in this way when you have a group of cells you don't see a double border.
You can also set the border for the grid using the Grid.BorderStyle property.
See form sample 26 for more information.
ToolTip You can bind a ToolTip on each cell. You must create a SourceGrid.Cells.Controllers.ToolTipText controller and associate it to a cell. Here an example:
SourceGrid.Cells.Controllers.ToolTipText toolTipController = new SourceGrid.Cells.Controllers.ToolTipText();toolTipController.ToolTipTitle = "ToolTip example";toolTipController.ToolTipIcon = ToolTipIcon.Info;toolTipController.IsBalloon = true;grid1[r, c] = new SourceGrid.Cells.Cell("Hello");grid1[r, c].ToolTipText = "Example of tooltip, bla bla bla ....";grid1[r, c].AddController(toolTipController); The ToolTipText property of the cell automatically populates a SourceGrid.Cells.Models.IToolTipText interface bound to the standard cell.
See form sample 26 for more information.
Note: To use the ToolTip on a GridVirtual you must define your custom SourceGrid.Cells.Models.IToolTipText implementation that read the value from your data source and then add the controller and the model to the virtual cell. See form sample 41.
ContextMenu You can create a ContextMenu (PopUp Menu) for a cell using the code below. First define a controller with the ContextMenu:
//Define a controller with a ContextMenupublic class PopupMenu : SourceGrid.Cells.Controllers.ControllerBase{ ContextMenu menu = new ContextMenu(); public PopupMenu() { menu.MenuItems.Add("Menu 1", new EventHandler(Menu1_Click)); menu.MenuItems.Add("Menu 2", new EventHandler(Menu2_Click)); } public override void OnMouseUp(SourceGrid.CellContext sender, MouseEventArgs e) { base.OnMouseUp (sender, e); if (e.Button == MouseButtons.Right) menu.Show(sender.Grid, new Point(e.X, e.Y)); } private void Menu1_Click(object sender, EventArgs e) { //TODO Your code here } private void Menu2_Click(object sender, EventArgs e) { //TODO Your code here }} Then add the controller to a cell:
PopupMenu menuController = new PopupMenu();...grid1[r, c] = new SourceGrid.Cells.Cell("Hello");grid1[r, c].AddController(menuController); See form sample 26 for more information.
Clipboard SourceGrid supports clipboard copy, paste and cut operations. To enable these features you can use this code:
grid1.ClipboardMode = SourceGrid.ClipboardMode.All; The user can then copy, paste and cut the selected cells using Ctrl+C, Ctrl+V or Ctrl+X or delete the content using Delete key.
Drag and Drop NOT SUPPORTED: From version 4.5 drag and drop is no more supported, I will try to insert this feature again soon.
Suggestions Usually with SourceGrid you must do all the work with code, for this reason one import suggestion is to organize it in a good and reusable manner. Here some tips:
If you need to customize some aspects of the cell I usually suggest to create a new class and write your customization code here. In this manner you can reuse your class in all your application and forms. Suppose for example that you want to create all the cells with a gray back color, you can write these new classes:
public class GrayView : SourceGrid.Cells.Views.Cell{ public new static readonly GrayView Default = new GrayView(); public GrayView() { BackColor = Color.LightGray; }}public class GrayCell : SourceGrid.Cells.Cell{ public GrayCell(object val):base(val) { View = GrayView.Default; }}This rule can be applied to any aspects of the grid, for example you can create a new Controller class and use it in your cell.
Another important feature that we can see in the previous code is that I have assigned the View property from a static variable. In this way you can share the same instance with many cells, and optimize the resources of the system.
Another little suggestion is about the use of namespaces. Many SourceGrid classes have the same name of some system classes. For example there is a CheckBox cell with the same name of the CheckBox control of System.Windows.Forms, for this reason is sometime difficult to use a normal using statement. If you don't like to use a long namespace and want a more readable code I suggest to rename the namespace in the using statement. For example you can replace this code:
SourceGrid.Cells.Button bt = new SourceGrid.Cells.Button();with:
using Cells = SourceGrid.Cells;.................Cells.Button bt = new Cells.Button();Extensions Other then the default Grid control there are some extensions that can be used in some specific cases. You can directly use one of these extensions or you can copy the code and create your own extension.
DataGrid SourceGrid.DataGrid is control derived from GridVirtual used for binding the data to a DevAge.ComponentModel.BoundListBase class.
The BoundListBase is an abstract class that can be used to as a generic layer to binding any kind of list control to a list data source.
Typically a data source is a System.Data.DataView or a custom list class. Currently there are 2 concrete classes that use BoundListBase:
- DevAge.ComponentModel.BoundDataView - Used for System.Data.DataView.
- DevAge.ComponentModel.BoundList<T> - Used for any List<T> class. You can use any kind of object with a default constructor and public property.
Basically the DataGrid control uses a special Model class of type IValueModel that reads the data directly from the data source. SourceGrid.DataGrid has a property DataSource used to store the BoundListBase object. Here is a simple example on how to use this control:
//Create a sample DataTableDataTable table = new DataTable();table.Columns.Add("A", typeof(string));table.Columns.Add("B", typeof(bool));table.Rows.Add(new object[]{"Row 1", false});table.Rows.Add(new object[]{"Row 2", true});table.Rows.Add(new object[]{"Row 3", false});dataGrid1.DataSource = new DevAge.ComponentModel.BoundDataView(table.DefaultView);In the previous code I have created a DataTable with 2 columns and some rows, then you can use the DefaultView property to retrieve a DataView class and assign it to the DataGrid control by creating an instance of a BoundDataView class. If you want you can customize the columns using the Columns property. This property returns a collection of DataGridColumn objects, you can customize each column to create customized cells. Here is an example:
//Create a custom View classSourceGrid.Cells.Views.Cell view = new SourceGrid.Cells.Views.Cell();view.BackColor = Color.LightBlue;//Manually add the columnSourceGrid.DataGridColumn gridColumn;gridColumn = dataGrid.Columns.Add("Country", "Country", typeof(string));gridColumn.DataCell.View = view;In this example I have manually created a column and assigned a LightBlue back color at the cell.
You can also use the DataGridColumn.Conditions to dynamically change the data cell. For example in the following code I create a condition to use a different cell backcolor for even rows (alternate backcolor):
SourceGrid.Conditions.ICondition condition = SourceGrid.Conditions.ConditionBuilder.AlternateView(gridColumn.DataCell.View, Color.LightGray, Color.Black);gridColumn.Conditions.Add(condition);In the following other example I create condition to use a View with a bold font and a green forecolor when a specific column is true.
SourceGrid.Conditions.ConditionView selectedConditionBold = new SourceGrid.Conditions.ConditionView(viewSelected);selectedConditionBold.EvaluateFunction = delegate(SourceGrid.DataGridColumn column, int gridRow, object itemRow) { DataRowView row = (DataRowView)itemRow; return row["Selected"] is bool && (bool)row["Selected"] == true; };gridColumn.Conditions.Add(selectedConditionBold);Currently there are 2 types of conditions: SourceGrid.Conditions.ConditionView that can be used to use a special view and SourceGrid.Conditions.ConditionCell to use a completely different cell. Both conditions can be used with a delegate to evaluate the row using your specific code.
In the sample project you can find more examples and code.
ArrayGrid SourceGrid.ArrayGrid is a control derived from GridVirtual used to bind the grid to an array. You can use this control setting the DataSource property with any System.Array. You can then customize the cells using the ValueCell, Header, RowHeader and ColumnHeader properties.
PlanningGrid SourceGrid.Planning.PlanningGrid control is a UserControl that internally use a real Grid to create a grid that can be used to show appointments. You can call the LoadPlanning method to set the range of the visible days and hours, and then add the appointments using the Appointments properties. This is a collection of IAppointment interface (implemented by the AppointmentBase class).
Each appointment has a View property that can be used to customize the appointment cell.
References DevAgeSourcePack references these assemblies:
- DevAge.Core.dll, DevAge.Windows.Forms.dll - An open source library with many commons features for .NET. Contains the core of the drawing library and some of the controls used as editors. You can find this library at DevAgeSourcePack article
Remember to redistribute these assemblies with SourceGrid.dll.
Future developments - Improve performance.
- Support for other platform: PocketPC, Mono, ...
- Better support for Windows Forms designer and other WYSIWYG features.
VB.NET As any .NET control you can use SourceGrid with any .NET language, also VB.NET. Unfortunately I don't have any example for VB.NET, consider anyway that the code is very similar to C#. Here some of the more common differences:C# | VB.NET | double x; | Dim x as Double | typeof(string) | GetType(String) | Class.Event += new EventHandler(Class_Event); | AddHandler Class.Event, Addressof Class_Event | grid[r,c] | grid.Item(r,c) | public class Dog{ public Dog() { } public string Name { get{return mName;} set{mName = value;} }} | Public class Dog Public sub New() End sub Public Property Name() as String Get Return mName End Get Set mName = Value End Set End PropertyEnd class | List<string> x; | Dim x as List(Of String) | FAQ Frequently Asked Questions:
Q: Can I use this project with Visual Studio 2005?
A: Yes, SourceGrid is compiled with .NET 2 and Visual Studio 2005.
Q: Can I use this project with Visual Studio 2003?
A: No, SourceGrid is compiled with .NET 2 and Visual Studio 2005. If you want you can use an older version (like SourceGrid 3).
Q: How can I create a tree view with SourceGrid? (hierarchical view)
A: For now SourceGrid doesn't support this kind of view. I hope to work on this for a future release.
Q: Can I use these controls with ASP.NET?
A: No, these are Windows Forms Controls. With Internet Explorer you can host a Windows Forms Control inside an html page, but it is usually not a good solution for web pages.
Q: Can I use these controls with .NET Compact Framework? And with Mono?
A: Currently this project is compatible only with Microsoft .NET Framework and Windows platforms. I'm working for porting some of the code to Mono and Compact Framework. Consider anyway that all the code is written with managed C# so probably it is not too difficult to use this library with other frameworks.
Special ThanksA special thanks to all who have helped to make this project with suggestions, bug reports, ideas and code.
I've also benefited greatly from:
History 4.11 (27 Nov 2007)- IMPORTANT: Optimized drawing code to draw only the invalidated region (thanks to Xentor for the suggestions).
- IMPORTANT: Optimized selection code to invalidated only the changed region (thanks to Xentor for the suggestions).
- Changed the RangeRegion class to be directly a collection (ICollection) of Range objects. Removed the GetRanges method that now is no more required because you can directly access and iterate the Range using the RangeRegion class.
- Changed the SelectionChanged event to use the new RangeRegionChangedEventArgs.
- Fixed the DataGrid to check if the edit of the datasource is enabled (AllowEdit) when editing rows.
4.10 (16 Oct 2007)- Fixed a bug in the RecalcCustomScrollBars when moving the focus on a partial visible row/column and both scrollbars are visible. Now I correctly calculate the rows to scroll.
- Added the DataGridRows.DataSourceIndexToGridRowIndex method to convert a DataSource index to a grid row index.
- Added the property ElementsDrawMode to the ViewBase class to support 'covering' drawing mode for the elements.
- Changed the order of the event dispatched to fix some problems when you remove, add or change a row inside an event (for example MouseDown, MouseUp, Click). Now I first process system events and then custom events.
- Fixed a bug on the ComboBox control when using a value not in the list and enter and leave the editing from another ComboBox.
- Fixed a display bug in the editors to show the control only after changing the value to reduce the flickering.
- Fixed a bug when drawing merged cells, to not draw many times the same cells
- Updated the DevAgeSourcePack references to version 4.10 to fix some bugs (see DevAgeSourcePack History section for details)
4.9 (17 June 2007)- IMPORTANT:Added the ComboBox View to draw a ComboBox on the cell not only when activating the editor. See form 14 for an example.
- Fixed a bug in the Rows/Columns to block AutoSize and Stretch for invisible columns/rows.
- Fixed a bug in the ColumnsInsideRegion and RowsInsideRegion methods for invisible columns/rows
- Extended sample 41 to show how to use select a DataGrid row and show the current selected row.
- Fixed a strange bug when using Selection.Focus(Position.Emtpy) that cause the grid to receive the focus.
- Fixed a bug in the RangeData.LoadData method to check if a value can be converted to string, used for example with the clipboard copy operation.
- Updated the DevAgeSourcePack references to version 4.9 to fix some bugs (see DevAgeSourcePack History section for details)
- Fixed a bug in the scroll code with big fixed rows or columns, thanks to Sacha.
- Fixed a bug when exporting the grid to an image with merged cells (RowSpan/ColumnSpan > 0).
- Added a Grid property to the PlanningGrid to get the internal grid instance.
- Restored the old code for the Button or Link cell using the KeyDown event to fire the action following the system Button behavior.
- Marked as obsolete the CellControl class replaced by the Grid.LinkedControls collection.
- Fixed a bug when using RemoveFocusCellOnLeave (to don't reset the selection)
- Fixed a bug when drawing the selection border and there is a single selected range
- Fixed a bug when using FocusFirstCellOnEnter to move the focus on the selection if there is a valid selected range (FocusFirstCell method)
- Added the ignorePartial parameter in the ShowCell method to don't move the scrollbars when the user move the focus on a partial visible cell.
- Fixed a bug in the Selection.ResetSelect and in the Selection.Focus when removing cells
4.8 (6 May 2007)- Updated the DevAgeSourcePack references to version 4.8 to fix some bugs (see DevAgeSourcePack History section for details)
- Renamed IBindedList to IBoundList
- Renamed BindedListBase to BoundListBase
- Renamed BindedList to BoundList
- Renamed BindedDataView to BoundDataView
- Fixed a bug in the TextBoxUITypeEditor when the text is not valid, especially for the DateTime editor (1615918).
- Fixed a bug in the AutoSize and Measure of merged cells that caused the merged cells to not autosize correctly (1601792).
- Signed SourceGrid assemblies with the .snk file
- Replaced the BindedListBase with the IBoundList interface in the DataGrid implementation
- Added a Visible property to the ColumnInfo and RowInfo class to show or hide columns or rows. For example you can hide a column with this code: grid1.Columns[0].Visible = false;. See form 50 for an example. (1569378)
- Fixed a bug in the CellControl.UnBindToGrid method, used when removing or replacing CellControl cells.
- Added support for nullable checkbox value. Now when the value of a checkbox is null the Undefined checkbox status is used. The Checked property now returns a Nullable bool value (bool?).
- Fixed documentation English errors
- Added HeaderHeight property in the DataGridRows class, which can be used to set the header height of the DataGrid control. (1604395)
4.7 (16 April 2007)- Fixed a bug in the scroll code (ShowCell method)
- Extended the Controller documentation
4.6 (15 April 2007)- Fixed the SourceGrid.Cells.Views.Button to show when the button has the focus.
- Fixed a bug when using a Button or Link cell that cause the execute event to be fired many times when you hold the key Space. Now I have handled the event on the KeyUp and added the Enter key (before I used the KeyPress).
- Removed the border default padding to fix some bugs on the cell borders
- Updated the DevAgeSourcePack references to version 4.6
- Fixed the scrollbars to scroll only the required columns/rows and correctly stop at the end
- Fixed a bug on the Measure method used to AutoSize the columns and rows size
- Added the CHM documentation api reference using Sandcastle
4.5 BETA (18 March 2007)This is a major release with many inportant changes and improvements. Consider that this is a BETA release and probably there are still some bugs and problems. This version can can be unstable. Use the forum for submitting bugs or if you have problems.
- IMPORTANT:New structure of the selection class. See 'Focus and Selection' paragraph in this article for more information.
- IMPORTANT:New SourceGrid.DataGrid class that now support also custom object binding and reviewed some code. See DataGrid section for more information.
- IMPORTANT:New internal structure of the SourceGrid.Grid class, to store rows and columns information in a list object for better performance.
- IMPORTANT:Removed all the Panels structure (GridSubPanel class).
- IMPORTANT:Reviewed positioning methods
- IMPORTANT:Reviewed view methods to customize sub elements (IText, IImage, ...)
- IMPORTANT:Reviewed grid controllers and events structure.
- IMPORTANT:Events and methods more integrated with the standard .NET conventions
- IMPORTANT:Updated DevAgeSourcePack references to version 4.3
- IMPORTANT:Removed many obsolete code
- IMPORTANT:Removed drag and drop support (I will try to implement it again soon)
- Fixed a bug on handling TabStop property and Tab navigation. Now the grid move the focus on the other controls of the form when required.
- Added the property Editor.UseCellViewProperties. The default is true. Set this property to false to manually change the editor control ForeColor, BackColor and Font, otherwise the editor read these properties from the View class.
- Added the event Editor.KeyPress that can be used to handle any key press of the editor (also when the user start the edit operation with a key)
- Fixed a bug in the ComboBox when using DropDownList and custom display text
- Removed resizable headers for ArrayGrid
- Fixed a bug in the NumericUpDown editor to correctly use Maximum, Minimum and Increment variables
- Fixed a bug when changing the active cell and in the code executed when the grid lost the focus. Now only if requred the focus is moved inside the grid. The bug caused the grid to receive the focus when calling grid.Selection.Focus(Empty). See Selection.Focus method for more information.
- Added an example on form 3 that use GDI+ drawing features.
- Changed the clipboard implementation. See Clipboard section for more information.
- Fixed a bug on some Views copy constructor (clone).
- Added to the form 3 a sample to to implement an editor to select a file using OpenFileDialog.
- Changed the PlanningGrid control to don't stretch or autosize the first 2 column headers.
- Improved the PlanningGrid control. Added the PlanningGrid.AppointmentClick and PlanningGrid.AppointmentDoubleClick events that can be used when the used click on the grid and reviewed some of the code.
- Moved the SelectionMode property from grid.Selection.SelectionMode to grid.SelectionMode
- Removed the GridVirtual.InvalidateCells method (use directly the GridVirtual.Invalidate)
- New schema version with automatic revision and build numbers
- Removed the selection events on the cell Controller. If you need to customized the selection you must directly use the Selection object.
- New structure for the LinkedControlList (Editors and CellControl)
- Added the sample form 49 to show the use of the DataGrid bound with custom entities
- Reviewed sample code and documentation
- Removed the StyleGrid property, style no more supported
4.0.0.4 BETA (10 Nov 2006)- Update references to DevAgeSourcePack 4.0.0.8. (Removed ODL.dll reference)
- Improved View classes for a better customization. Now support flat headers, not themed headers, alternate back color, linear gradient, .... See View and form 28 or 48 for an example. (Request ID: 1571395)
- Fixed a bug when drawing merged cells (ColSpan or RowSpan > 1) (Request ID: 1588870).
- Fixed a bug to show the scrollbars only when necessary (Request ID: 1584957)
- Fixed a bug in the MouseSelection class to don't execute again the Editor.EndEdit, because it is already executed inside the Controllers.Grid
- Changed the View.Border property to return an IBorder instance. The previous RectangleBorder class implements the IBorder interface, but this interface can also be implemented by different border style. See also See Border
- Fixed a bug to correctly call GiveFeedback event, and some other minors improvements. (Request ID: 1585697)
- Fixed the Button and CheckBox controllers to execute the action only when the left mouse button is pressed.
- Added new features for the ToolTip. Now you can set the Icon, Title, BackColor and ForeColor properties of the ToolTipText Controller. See ToolTip or form sample 26 for more information.
- Removed the GridToolTipActive property (no more used, probably you must remove the property from the designer generated code).
- Improved AutoScroll and IsVisibleCell test. Now if a cell is partially visible the autoscroll is not executed.
4.0.0.3 BETA (13 October 2006)- Fixed a bug in the invalidate method that caused the cells to don't refresh correctly.
- Fixed a bug in the editors when start editing with a keybord key. Now only the TextBox use the key. I have removed the SendKeys features because some problems on international keybords.
- Fixed a bug when using the & character inside a cell text.
- Update references to DevAgeSourcePack 4.0.0.5
- Improved the mouse multi selection code and automatic scrolling.
4.0.0.2 BETA (08 October 2006)- Changed some internal structure of the View class for better flexibility.
- Extended "Sample 3" to show how to implement rotated text (see RotateTextView).
- Fixed some important bugs for the scrollbars.
- Reviewed many internal parts to handle scrolling and to calculate positions of the cells. Now all the cell positions are relative to the current view, so there is no more the concept of an aboslute cell position. This is usefull to correctly handle grid with many rows.
- Implemented the AutoSizeMode features also for GridVirtual derived grids.
- Updated references to DevAgeSourcePack 4.0.0.4
- Fixed a bug in the AutoSize methods.
4.0.0.1 BETA (01 October 2006)SourceGrid 4 is the evolution of the SourceGrid 3 control. The major differences are:
- Some minor corrections for VS 2005
- Replaced Grid.AutoSize method with Grid.AutoSizeCells
- Changed the default selection border width to 2 pixels
- Changed the ComboBoxType control with the DevAgeComboBox. DevAgeComboBox is a new class that internally use the system ComboBox for a better compatibility and a more robust code support.
- Replaced the TypedComboBox, TypedTextBox and other windows form controls with the DevAgeCombo, DevAgeTextBox, ... for better compatibility using system controls.
- Review some of the code for the Validator classes and added a Changed event.
- Fixed some error when display UITypeEditor controls.
- Added a RectangleBorderRelative property to the Selection and the HighlightedRange class, used to fix a problem when drawing range on fixed cols or rows
- Added MultiColumnsComparer, to sort multiple columns automatically
- Added Selection.MoveActiveCell method to move the focus to a specific direction. Used with the arrow and tab keys.
- Added the new DevAge.Drawing.VisualElements classes to draw elements parts (image, text, xp theme element, ...). This is basically a little drawing framework that support aggregation of parts of elements.
- Used the new DevAge.Drawing.VisualElements for all SourceGrid cells drawing.
- Removed the DevAge.WindowsPlatform project. Now all the XP theme support is 100% managed (no Interop or windows API).
- Merged the DevAge.Data and DevAge.Utilities with the DevAge.Core project.
- Merged the DevAge.Drawing project with the DevAge.Windows.Forms project.
- Used the new TextRenderer class.
- Add the ability to change the Font of the cell headers
- Added the Mirrored property for RTL (RightToLeft support)
- Moved the SourceGrid3.Cells.Real classes to the namespace SourceGrid3.Cells for a more compact naming.
- Renamed SourceGrid3 namespace to SourceGrid
- Renamed DevAge.SourceGrid3 assembly to DevAge.SourceGrid
- Renamed DevAge.SourceGrid3.Extensions assembly to DevAge.SourceGrid.Extension
- SourceGrid.Utilities.CreateEditor replaced with SourceGrid.Cells.Editors.Factory.Create
Previous versions You can find more information about previous SourceGrid versions at this link: http://www.devage.com/
License SourceGrid LICENSE (MIT style)
Copyright (c) 2006 www.devage.com, Davide Icardi
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[ 本帖最后由 shenlili 于 2008-12-24 15:47 编辑 ] |
评分
-
查看全部评分
|