1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005,2006 Novell, Inc. (http://www.novell.com)
23 // Jordi Mas i Hernandez <jordi@ximian.com>
24 // Chris Toshok <toshok@ximian.com>
29 using System.ComponentModel;
32 using System.Runtime.InteropServices;
33 using System.Collections;
36 namespace System.Windows.Forms
38 internal class DataGridRelationshipRow {
41 public DataGridRelationshipRow (DataGrid owner)
49 relation_area = Rectangle.Empty;
54 /* this needs to be a property so that the Autosize
55 * example from the Windows.Forms FAQ will work */
57 get { return height; }
59 if (height != value) {
61 owner.UpdateRowsFrom (this);
66 public bool IsSelected;
67 public bool IsExpanded;
68 public int VerticalOffset;
69 public int RelationHeight;
70 public Rectangle relation_area; /* the Y coordinate of this rectangle is updated as needed */
73 internal class DataGridDataSource
75 public DataGrid owner;
76 public CurrencyManager list_manager;
78 public string data_member;
79 public object data_source;
80 public DataGridCell current;
82 public DataGridDataSource (DataGrid owner, CurrencyManager list_manager, object data_source, string data_member, object view_data, DataGridCell current)
85 this.list_manager = list_manager;
86 this.view = view_data;
87 this.data_source = data_source;
88 this.data_member = data_member;
89 this.current = current;
92 DataGridRelationshipRow[] rows;
93 public DataGridRelationshipRow[] Rows {
98 Hashtable selected_rows;
99 public Hashtable SelectedRows {
100 get { return selected_rows; }
101 set { selected_rows = value; }
105 public int SelectionStart {
106 get { return selection_start; }
107 set { selection_start = value; }
111 [DefaultEvent("Navigate")]
112 [DefaultProperty("DataSource")]
113 [Designer("System.Windows.Forms.Design.DataGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
115 [ComplexBindingProperties ("DataSource", "DataMember")]
116 [ClassInterface (ClassInterfaceType.AutoDispatch)]
119 public class DataGrid : Control, ISupportInitialize, IDataGridEditingService
125 public enum HitTestType
137 public sealed class HitTestInfo
139 public static readonly HitTestInfo Nowhere = null;
143 DataGrid.HitTestType type;
145 #region Private Constructors
146 internal HitTestInfo () : this (-1, -1, HitTestType.None)
150 internal HitTestInfo (int row, int column, DataGrid.HitTestType type)
153 this.column = column;
159 #region Public Instance Properties
161 get { return column; }
167 public DataGrid.HitTestType Type {
170 #endregion //Public Instance Properties
172 public override bool Equals (object value)
174 if (!(value is HitTestInfo))
177 HitTestInfo obj = (HitTestInfo) value;
178 return (obj.Column == column && obj.Row == row && obj.Type ==type);
181 public override int GetHashCode ()
186 public override string ToString ()
188 return "{ " + type + "," + row + "," + column + "}";
192 #region Local Variables
193 /* cached theme defaults */
194 static readonly Color def_background_color = ThemeEngine.Current.DataGridBackgroundColor;
195 static readonly Color def_caption_backcolor = ThemeEngine.Current.DataGridCaptionBackColor;
196 static readonly Color def_caption_forecolor = ThemeEngine.Current.DataGridCaptionForeColor;
197 static readonly Color def_parent_rows_backcolor = ThemeEngine.Current.DataGridParentRowsBackColor;
198 static readonly Color def_parent_rows_forecolor = ThemeEngine.Current.DataGridParentRowsForeColor;
201 // XXX this needs addressing. Control.background_color should not be internal.
202 new Color background_color;
203 Color caption_backcolor;
204 Color caption_forecolor;
205 Color parent_rows_backcolor;
206 Color parent_rows_forecolor;
208 /* flags to determine which areas of the datagrid are shown */
209 bool caption_visible;
210 bool parent_rows_visible;
212 GridTableStylesCollection styles_collection;
213 DataGridParentRowsLabelStyle parent_rows_label_style;
214 DataGridTableStyle default_style;
215 DataGridTableStyle grid_style;
216 DataGridTableStyle current_style;
219 DataGridCell current_cell;
220 Hashtable selected_rows;
221 int selection_start; // used for range selection
223 /* layout/rendering */
224 bool allow_navigation;
225 int first_visible_row;
226 int first_visible_column;
227 int visible_row_count;
228 int visible_column_count;
232 HScrollBar horiz_scrollbar;
233 VScrollBar vert_scrollbar;
234 int horiz_pixeloffset;
236 internal Bitmap back_button_image;
237 internal Rectangle back_button_rect;
238 internal bool back_button_mouseover;
239 internal bool back_button_active;
240 internal Bitmap parent_rows_button_image;
241 internal Rectangle parent_rows_button_rect;
242 internal bool parent_rows_button_mouseover;
243 internal bool parent_rows_button_active;
248 CurrencyManager list_manager;
249 bool refetch_list_manager = true;
251 DataGridRelationshipRow[] rows;
253 /* column resize fields */
254 bool column_resize_active;
256 int resize_column_width_delta;
259 /* row resize fields */
260 bool row_resize_active;
262 int resize_row_height_delta;
265 /* used to make sure we don't endlessly recurse calling set_CurrentCell and OnListManagerPositionChanged */
266 bool from_positionchanged_handler;
269 bool cursor_in_add_row;
270 bool add_row_changed;
271 bool is_editing; // Current cell is edit mode
274 internal Stack data_source_stack;
276 #endregion // Local Variables
278 #region Public Constructors
281 allow_navigation = true;
282 background_color = def_background_color;
283 border_style = BorderStyle.Fixed3D;
284 caption_backcolor = def_caption_backcolor;
285 caption_forecolor = def_caption_forecolor;
286 caption_text = string.Empty;
287 caption_visible = true;
288 datamember = string.Empty;
289 parent_rows_backcolor = def_parent_rows_backcolor;
290 parent_rows_forecolor = def_parent_rows_forecolor;
291 parent_rows_visible = true;
292 current_cell = new DataGridCell ();
293 parent_rows_label_style = DataGridParentRowsLabelStyle.Both;
294 selected_rows = new Hashtable ();
295 selection_start = -1;
296 rows = new DataGridRelationshipRow [0];
298 default_style = new DataGridTableStyle (true);
299 grid_style = new DataGridTableStyle ();
301 styles_collection = new GridTableStylesCollection (this);
302 styles_collection.CollectionChanged += new CollectionChangeEventHandler (OnTableStylesCollectionChanged);
304 CurrentTableStyle = grid_style;
306 horiz_scrollbar = new ImplicitHScrollBar ();
307 horiz_scrollbar.Scroll += new ScrollEventHandler (GridHScrolled);
308 vert_scrollbar = new ImplicitVScrollBar ();
309 vert_scrollbar.Scroll += new ScrollEventHandler (GridVScrolled);
311 SetStyle (ControlStyles.UserMouse, true);
313 data_source_stack = new Stack ();
315 back_button_image = ResourceImageLoader.Get ("go-previous.png");
316 back_button_image.MakeTransparent (Color.Transparent);
317 parent_rows_button_image = ResourceImageLoader.Get ("go-top.png");
318 parent_rows_button_image.MakeTransparent (Color.Transparent);
321 #endregion // Public Constructor
323 #region Public Instance Properties
326 public bool AllowNavigation {
327 get { return allow_navigation; }
329 if (allow_navigation != value) {
330 allow_navigation = value;
331 OnAllowNavigationChanged (EventArgs.Empty);
337 public bool AllowSorting {
338 get { return grid_style.AllowSorting; }
339 set { grid_style.AllowSorting = value; }
342 public Color AlternatingBackColor {
343 get { return grid_style.AlternatingBackColor; }
344 set { grid_style.AlternatingBackColor = value; }
347 public override Color BackColor {
348 get { return grid_style.BackColor; }
349 set { grid_style.BackColor = value; }
352 public Color BackgroundColor {
353 get { return background_color; }
355 if (background_color != value) {
356 background_color = value;
357 OnBackgroundColorChanged (EventArgs.Empty);
364 [EditorBrowsable(EditorBrowsableState.Never)]
365 public override Image BackgroundImage {
366 get { return base.BackgroundImage; }
368 if (base.BackgroundImage == value)
371 base.BackgroundImage = value;
378 [EditorBrowsable (EditorBrowsableState.Never)]
379 public override ImageLayout BackgroundImageLayout {
380 get { return base.BackgroundImageLayout; }
381 set { base.BackgroundImageLayout = value; }
386 [DefaultValue(BorderStyle.Fixed3D)]
387 public BorderStyle BorderStyle {
388 get { return InternalBorderStyle; }
390 InternalBorderStyle = value;
391 CalcAreasAndInvalidate ();
392 OnBorderStyleChanged (EventArgs.Empty);
396 public Color CaptionBackColor {
397 get { return caption_backcolor; }
399 if (caption_backcolor != value) {
400 caption_backcolor = value;
401 InvalidateCaption ();
408 public Font CaptionFont {
410 if (caption_font == null)
411 return new Font (Font, FontStyle.Bold);
416 if (caption_font != null && caption_font.Equals (value))
419 caption_font = value;
420 CalcAreasAndInvalidate ();
424 public Color CaptionForeColor {
425 get { return caption_forecolor; }
427 if (caption_forecolor != value) {
428 caption_forecolor = value;
429 InvalidateCaption ();
436 public string CaptionText {
437 get { return caption_text; }
439 if (caption_text != value) {
440 caption_text = value;
441 InvalidateCaption ();
447 public bool CaptionVisible {
448 get { return caption_visible; }
450 if (caption_visible != value) {
452 caption_visible = value;
453 CalcAreasAndInvalidate ();
454 OnCaptionVisibleChanged (EventArgs.Empty);
460 public bool ColumnHeadersVisible {
461 get { return grid_style.ColumnHeadersVisible; }
462 set { grid_style.ColumnHeadersVisible = value; }
465 bool setting_current_cell;
468 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
469 public DataGridCell CurrentCell {
470 get { return current_cell; }
472 if (setting_current_cell)
474 setting_current_cell = true;
476 if (!IsHandleCreated) {
477 setting_current_cell = false;
478 throw new Exception ("CurrentCell cannot be set at this time.");
481 if (current_cell.Equals (value)) {
482 setting_current_cell = false;
486 /* make sure the new cell fits in the correct bounds for [row,column] */
487 if (ReadOnly && value.RowNumber > RowsCount - 1)
488 value.RowNumber = RowsCount - 1;
489 else if (value.RowNumber > RowsCount)
490 value.RowNumber = RowsCount;
491 if (value.ColumnNumber >= CurrentTableStyle.GridColumnStyles.Count)
492 value.ColumnNumber = CurrentTableStyle.GridColumnStyles.Count == 0 ? 0 : CurrentTableStyle.GridColumnStyles.Count - 1;
495 /* now make sure we don't go negative */
496 if (value.RowNumber < 0) value.RowNumber = 0;
497 if (value.ColumnNumber < 0) value.ColumnNumber = 0;
499 bool was_changing = is_changing;
501 add_row_changed = add_row_changed || was_changing;
504 if (value.RowNumber != current_cell.RowNumber) {
505 if (!from_positionchanged_handler) {
507 ListManager.EndCurrentEdit ();
509 catch (Exception e) {
510 DialogResult r = MessageBox.Show (String.Format ("{0} Do you wish to correct the value?", e.Message),
511 "Error when committing the row to the original data source",
512 MessageBoxButtons.YesNo);
513 if (r == DialogResult.Yes) {
518 ListManager.CancelCurrentEdit ();
522 if (value.RowNumber == RowsCount && !ListManager.CanAddRows)
526 int old_row = current_cell.RowNumber;
528 current_cell = value;
530 EnsureCellVisibility (value);
532 if (CurrentRow == RowsCount && ListManager.CanAddRows) {
533 cursor_in_add_row = true;
534 add_row_changed = false;
538 cursor_in_add_row = false;
541 InvalidateRowHeader (old_row);
542 InvalidateRowHeader (current_cell.RowNumber);
544 list_manager.Position = current_cell.RowNumber;
546 OnCurrentCellChanged (EventArgs.Empty);
548 if (!from_positionchanged_handler)
551 setting_current_cell = false;
556 get { return current_cell.RowNumber; }
557 set { CurrentCell = new DataGridCell (value, current_cell.ColumnNumber); }
561 get { return current_cell.ColumnNumber; }
562 set { CurrentCell = new DataGridCell (current_cell.RowNumber, value); }
566 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
567 public int CurrentRowIndex {
569 if (ListManager == null)
574 set { CurrentRow = value; }
578 [EditorBrowsable(EditorBrowsableState.Never)]
579 public override Cursor Cursor {
580 get { return base.Cursor; }
581 set { base.Cursor = value; }
585 [Editor ("System.Windows.Forms.Design.DataMemberListEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
586 public string DataMember {
587 get { return datamember; }
589 if (BindingContext != null) {
590 SetDataSource (datasource, value);
593 if (list_manager != null)
596 refetch_list_manager = true;
602 [RefreshProperties(RefreshProperties.Repaint)]
604 [AttributeProvider (typeof (IListSource))]
606 [TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " + Consts.AssemblySystem_Design)]
608 public object DataSource {
609 get { return datasource; }
611 if (BindingContext != null) {
612 SetDataSource (value, ListManager == null ? datamember : string.Empty);
616 if (list_manager != null)
617 datamember = string.Empty;
619 if (list_manager != null)
621 refetch_list_manager = true;
626 protected override Size DefaultSize {
627 get { return new Size (130, 80); }
631 public int FirstVisibleColumn {
632 get { return first_visible_column; }
635 [DefaultValue(false)]
636 public bool FlatMode {
637 get { return flatmode; }
639 if (flatmode != value) {
641 OnFlatModeChanged (EventArgs.Empty);
647 public override Color ForeColor {
648 get { return grid_style.ForeColor; }
649 set { grid_style.ForeColor = value; }
652 public Color GridLineColor {
653 get { return grid_style.GridLineColor; }
655 if (value == Color.Empty)
656 throw new ArgumentException ("Color.Empty value is invalid.");
658 grid_style.GridLineColor = value;
662 [DefaultValue(DataGridLineStyle.Solid)]
663 public DataGridLineStyle GridLineStyle {
664 get { return grid_style.GridLineStyle; }
665 set { grid_style.GridLineStyle = value; }
668 public Color HeaderBackColor {
669 get { return grid_style.HeaderBackColor; }
671 if (value == Color.Empty)
672 throw new ArgumentException ("Color.Empty value is invalid.");
674 grid_style.HeaderBackColor = value;
678 public Font HeaderFont {
679 get { return grid_style.HeaderFont; }
680 set { grid_style.HeaderFont = value; }
683 public Color HeaderForeColor {
684 get { return grid_style.HeaderForeColor; }
685 set { grid_style.HeaderForeColor = value; }
688 protected ScrollBar HorizScrollBar {
689 get { return horiz_scrollbar; }
691 internal ScrollBar HScrollBar {
692 get { return horiz_scrollbar; }
695 internal int HorizPixelOffset {
696 get { return horiz_pixeloffset; }
699 internal bool IsChanging {
700 get { return is_changing; }
703 public object this [DataGridCell cell] {
704 get { return this [cell.RowNumber, cell.ColumnNumber]; }
705 set { this [cell.RowNumber, cell.ColumnNumber] = value; }
708 public object this [int rowIndex, int columnIndex] {
709 get { return CurrentTableStyle.GridColumnStyles[columnIndex].GetColumnValueAtRow (ListManager,
711 set { CurrentTableStyle.GridColumnStyles[columnIndex].SetColumnValueAtRow (ListManager,
715 public Color LinkColor {
716 get { return grid_style.LinkColor; }
717 set { grid_style.LinkColor = value; }
720 internal Font LinkFont {
721 get { return new Font (Font, FontStyle.Underline); }
728 [EditorBrowsable(EditorBrowsableState.Never)]
729 public Color LinkHoverColor {
730 get { return grid_style.LinkHoverColor; }
731 set { grid_style.LinkHoverColor = value; }
735 [EditorBrowsable(EditorBrowsableState.Advanced)]
736 protected internal CurrencyManager ListManager {
738 if (list_manager == null && refetch_list_manager) {
739 SetDataSource (datasource, datamember);
740 refetch_list_manager = false;
745 set { throw new NotSupportedException ("Operation is not supported."); }
748 public Color ParentRowsBackColor {
749 get { return parent_rows_backcolor; }
751 if (parent_rows_backcolor != value) {
752 parent_rows_backcolor = value;
753 if (parent_rows_visible) {
760 public Color ParentRowsForeColor {
761 get { return parent_rows_forecolor; }
763 if (parent_rows_forecolor != value) {
764 parent_rows_forecolor = value;
765 if (parent_rows_visible) {
772 [DefaultValue(DataGridParentRowsLabelStyle.Both)]
773 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
774 public DataGridParentRowsLabelStyle ParentRowsLabelStyle {
775 get { return parent_rows_label_style; }
777 if (parent_rows_label_style != value) {
778 parent_rows_label_style = value;
779 if (parent_rows_visible) {
783 OnParentRowsLabelStyleChanged (EventArgs.Empty);
789 public bool ParentRowsVisible {
790 get { return parent_rows_visible; }
792 if (parent_rows_visible != value) {
793 parent_rows_visible = value;
794 CalcAreasAndInvalidate ();
795 OnParentRowsVisibleChanged (EventArgs.Empty);
800 // Settting this property seems to have no effect.
802 [TypeConverter(typeof(DataGridPreferredColumnWidthTypeConverter))]
803 public int PreferredColumnWidth {
804 get { return grid_style.PreferredColumnWidth; }
805 set { grid_style.PreferredColumnWidth = value; }
808 public int PreferredRowHeight {
809 get { return grid_style.PreferredRowHeight; }
810 set { grid_style.PreferredRowHeight = value; }
813 [DefaultValue(false)]
814 public bool ReadOnly {
815 get { return _readonly; }
817 if (_readonly != value) {
819 OnReadOnlyChanged (EventArgs.Empty);
820 CalcAreasAndInvalidate ();
826 public bool RowHeadersVisible {
827 get { return grid_style.RowHeadersVisible; }
828 set { grid_style.RowHeadersVisible = value; }
832 public int RowHeaderWidth {
833 get { return grid_style.RowHeaderWidth; }
834 set { grid_style.RowHeaderWidth = value; }
837 internal DataGridRelationshipRow[] DataGridRows {
842 public Color SelectionBackColor {
843 get { return grid_style.SelectionBackColor; }
844 set { grid_style.SelectionBackColor = value; }
847 public Color SelectionForeColor {
848 get { return grid_style.SelectionForeColor; }
849 set { grid_style.SelectionForeColor = value; }
852 public override ISite Site {
853 get { return base.Site; }
854 set { base.Site = value; }
858 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
859 public GridTableStylesCollection TableStyles {
860 get { return styles_collection; }
865 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
866 [EditorBrowsable(EditorBrowsableState.Never)]
867 public override string Text {
868 get { return base.Text; }
869 set { base.Text = value; }
873 [EditorBrowsable(EditorBrowsableState.Advanced)]
874 protected ScrollBar VertScrollBar {
875 get { return vert_scrollbar; }
877 internal ScrollBar VScrollBar {
878 get { return vert_scrollbar; }
882 public int VisibleColumnCount {
883 get { return visible_column_count; }
887 public int VisibleRowCount {
888 get { return visible_row_count; }
891 #endregion // Public Instance Properties
893 #region Private Instance Properties
894 internal DataGridTableStyle CurrentTableStyle {
895 get { return current_style; }
897 if (current_style != value) {
898 if (current_style != null)
899 DisconnectTableStyleEvents ();
901 current_style = value;
903 if (current_style != null) {
904 current_style.DataGrid = this;
905 ConnectTableStyleEvents ();
907 CalcAreasAndInvalidate ();
912 internal int FirstVisibleRow {
913 get { return first_visible_row; }
916 internal int RowsCount {
917 get { return ListManager != null ? ListManager.Count : 0; }
920 internal int RowHeight {
922 if (CurrentTableStyle.CurrentPreferredRowHeight > Font.Height + 3 + 1 /* line */)
923 return CurrentTableStyle.CurrentPreferredRowHeight;
925 return Font.Height + 3 + 1 /* line */;
929 internal override bool ScaleChildrenInternal {
930 get { return false; }
933 internal bool ShowEditRow {
935 if (ListManager != null && !ListManager.CanAddRows)
942 internal bool ShowParentRows {
943 get { return ParentRowsVisible && data_source_stack.Count > 0; }
946 #endregion Private Instance Properties
948 #region Public Instance Methods
953 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
955 InvalidateRowHeader (current_cell.RowNumber);
960 public bool BeginEdit (DataGridColumnStyle gridColumn, int rowNumber)
965 int column = CurrentTableStyle.GridColumnStyles.IndexOf (gridColumn);
969 CurrentCell = new DataGridCell (rowNumber, column);
971 /* force editing of CurrentCell if we aren't already editing */
977 public void BeginInit ()
981 protected virtual void CancelEditing ()
983 if (CurrentTableStyle.GridColumnStyles.Count == 0)
986 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].ConcedeFocus ();
989 if (current_cell.ColumnNumber < CurrentTableStyle.GridColumnStyles.Count)
990 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
991 InvalidateRowHeader (current_cell.RowNumber);
994 if (cursor_in_add_row && !is_changing) {
995 ListManager.CancelCurrentEdit ();
1003 public void Collapse (int row)
1005 if (!rows[row].IsExpanded)
1009 rows[row].IsExpanded = false;
1010 for (int i = 1; i < rows.Length - row; i ++)
1011 rows[row + i].VerticalOffset -= rows[row].RelationHeight;
1013 rows[row].height -= rows[row].RelationHeight;
1014 rows[row].RelationHeight = 0;
1015 ResumeLayout (false);
1017 /* XX need to redraw from @row down */
1018 CalcAreasAndInvalidate ();
1021 protected internal virtual void ColumnStartedEditing (Control editingControl)
1023 ColumnStartedEditing (editingControl.Bounds);
1026 protected internal virtual void ColumnStartedEditing (Rectangle bounds)
1028 bool need_invalidate = is_changing == false;
1029 // XXX calculate the row header to invalidate
1030 // instead of using CurrentRow
1033 if (cursor_in_add_row && need_invalidate)
1034 RecreateDataGridRows (true);
1036 if (need_invalidate)
1037 InvalidateRowHeader (CurrentRow);
1040 protected override AccessibleObject CreateAccessibilityInstance ()
1042 return base.CreateAccessibilityInstance ();
1045 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop)
1047 return CreateGridColumn (prop, false);
1050 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop, bool isDefault)
1052 throw new NotImplementedException();
1055 protected override void Dispose (bool disposing)
1057 base.Dispose (disposing);
1060 public bool EndEdit (DataGridColumnStyle gridColumn, int rowNumber, bool shouldAbort)
1062 if (shouldAbort || (_readonly || gridColumn.TableStyleReadOnly || gridColumn.ReadOnly))
1063 gridColumn.Abort (rowNumber);
1065 gridColumn.Commit (ListManager, rowNumber);
1066 gridColumn.ConcedeFocus ();
1069 if (is_editing || is_changing) {
1071 is_changing = false;
1072 InvalidateRowHeader (rowNumber);
1077 public void EndInit ()
1079 if (grid_style != null)
1080 grid_style.DataGrid = this;
1083 public void Expand (int row)
1085 if (rows[row].IsExpanded)
1088 rows[row].IsExpanded = true;
1092 string[] relations = CurrentTableStyle.Relations;
1093 StringBuilder relation_builder = new StringBuilder ("");
1095 for (i = 0; i < relations.Length; i ++) {
1097 relation_builder.Append ("\n");
1099 relation_builder.Append (relations[i]);
1101 string relation_text = relation_builder.ToString ();
1103 SizeF measured_area = TextRenderer.MeasureString (relation_text, LinkFont);
1105 rows[row].relation_area = new Rectangle (cells_area.X + 1,
1106 0, /* updated as needed at the usage sites for relation_area */
1107 (int)measured_area.Width + 4,
1108 Font.Height * relations.Length);
1110 for (i = 1; i < rows.Length - row; i ++)
1111 rows[row + i].VerticalOffset += rows[row].relation_area.Height;
1112 rows[row].height += rows[row].relation_area.Height;
1113 rows[row].RelationHeight = rows[row].relation_area.Height;
1115 /* XX need to redraw from @row down */
1116 CalcAreasAndInvalidate ();
1119 public Rectangle GetCellBounds (DataGridCell dgc)
1121 return GetCellBounds (dgc.RowNumber, dgc.ColumnNumber);
1124 public Rectangle GetCellBounds (int row, int col)
1126 Rectangle bounds = new Rectangle ();
1129 bounds.Width = CurrentTableStyle.GridColumnStyles[col].Width;
1130 bounds.Height = rows[row].Height - rows[row].RelationHeight;
1131 bounds.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1132 col_pixel = GetColumnStartingPixel (col);
1133 bounds.X = cells_area.X + col_pixel - horiz_pixeloffset;
1137 public Rectangle GetCurrentCellBounds ()
1139 return GetCellBounds (current_cell.RowNumber, current_cell.ColumnNumber);
1142 protected virtual string GetOutputTextDelimiter ()
1144 return string.Empty;
1147 protected virtual void GridHScrolled (object sender, ScrollEventArgs se)
1149 if (se.NewValue == horiz_pixeloffset ||
1150 se.Type == ScrollEventType.EndScroll) {
1154 ScrollToColumnInPixels (se.NewValue);
1157 protected virtual void GridVScrolled (object sender, ScrollEventArgs se)
1159 int old_first_visible_row = first_visible_row;
1160 first_visible_row = se.NewValue;
1162 if (first_visible_row == old_first_visible_row)
1165 UpdateVisibleRowCount ();
1167 if (first_visible_row == old_first_visible_row)
1170 ScrollToRow (old_first_visible_row, first_visible_row);
1173 public HitTestInfo HitTest (Point position)
1175 return HitTest (position.X, position.Y);
1178 const int RESIZE_HANDLE_HORIZ_SIZE = 5;
1179 const int RESIZE_HANDLE_VERT_SIZE = 3;
1181 // From Point to Cell
1182 public HitTestInfo HitTest (int x, int y)
1184 if (column_headers_area.Contains (x, y)) {
1185 int offset_x = x + horiz_pixeloffset;
1187 int column_under_mouse = FromPixelToColumn (offset_x, out column_x);
1189 if ((column_x + CurrentTableStyle.GridColumnStyles[column_under_mouse].Width - offset_x < RESIZE_HANDLE_HORIZ_SIZE)
1190 && column_under_mouse < CurrentTableStyle.GridColumnStyles.Count) {
1192 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnResize);
1195 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnHeader);
1199 if (row_headers_area.Contains (x, y)) {
1201 int rcnt = FirstVisibleRow + VisibleRowCount;
1202 for (int r = FirstVisibleRow; r < rcnt; r++) {
1203 posy = cells_area.Y + rows[r].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1204 if (y <= posy + rows[r].Height) {
1205 if ((posy + rows[r].Height) - y < RESIZE_HANDLE_VERT_SIZE) {
1206 return new HitTestInfo (r, -1, HitTestType.RowResize);
1209 return new HitTestInfo (r, -1, HitTestType.RowHeader);
1215 if (caption_area.Contains (x, y)) {
1216 return new HitTestInfo (-1, -1, HitTestType.Caption);
1219 if (parent_rows.Contains (x, y)) {
1220 return new HitTestInfo (-1, -1, HitTestType.ParentRows);
1223 int pos_y, pos_x, width;
1224 int rowcnt = FirstVisibleRow + VisibleRowCount;
1225 for (int row = FirstVisibleRow; row < rowcnt; row++) {
1227 pos_y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1228 if (y <= pos_y + rows[row].Height) {
1230 int column_cnt = first_visible_column + visible_column_count;
1231 if (column_cnt > 0) {
1232 for (int column = first_visible_column; column < column_cnt; column++) {
1233 if (CurrentTableStyle.GridColumnStyles[column].bound == false)
1235 col_pixel = GetColumnStartingPixel (column);
1236 pos_x = cells_area.X + col_pixel - horiz_pixeloffset;
1237 width = CurrentTableStyle.GridColumnStyles[column].Width;
1239 if (x <= pos_x + width) { // Column found
1240 return new HitTestInfo (row, column, HitTestType.Cell);
1244 else if (CurrentTableStyle.HasRelations) {
1245 /* XXX this needs checking against MS somehow... */
1246 if (x < rows[row].relation_area.X + rows[row].relation_area.Width)
1247 return new HitTestInfo (row, 0/*XXX?*/, HitTestType.Cell);
1254 return new HitTestInfo ();
1257 public bool IsExpanded (int rowNumber)
1259 return (rows[rowNumber].IsExpanded);
1262 public bool IsSelected (int row)
1264 return rows[row].IsSelected;
1268 public void NavigateBack ()
1270 if (data_source_stack.Count == 0)
1273 DataGridDataSource source = (DataGridDataSource)data_source_stack.Pop ();
1274 list_manager = source.list_manager;
1276 selected_rows = source.SelectedRows;
1277 selection_start = source.SelectionStart;
1278 SetDataSource (source.data_source, source.data_member);
1280 CurrentCell = source.current;
1284 public void NavigateTo (int rowNumber, string relationName)
1286 if (allow_navigation == false)
1289 DataGridDataSource previous_source = new DataGridDataSource (this, list_manager, datasource, datamember, list_manager.Current, CurrentCell);
1290 previous_source.Rows = rows;
1291 previous_source.SelectedRows = selected_rows;
1292 previous_source.SelectionStart = selection_start;
1294 data_source_stack.Push (previous_source);
1297 selected_rows = new Hashtable ();
1298 selection_start = -1;
1300 DataMember = String.Format ("{0}.{1}", DataMember, relationName);
1301 OnDataSourceChanged (EventArgs.Empty);
1304 protected virtual void OnAllowNavigationChanged (EventArgs e)
1306 EventHandler eh = (EventHandler)(Events [AllowNavigationChangedEvent]);
1311 protected void OnBackButtonClicked (object sender, EventArgs e)
1313 EventHandler eh = (EventHandler)(Events [BackButtonClickEvent]);
1318 protected override void OnBackColorChanged (EventArgs e)
1320 base.OnBackColorChanged (e);
1323 protected virtual void OnBackgroundColorChanged (EventArgs e)
1325 EventHandler eh = (EventHandler)(Events [BackgroundColorChangedEvent]);
1330 protected override void OnBindingContextChanged (EventArgs e)
1332 base.OnBindingContextChanged (e);
1334 SetDataSource (datasource, datamember);
1337 protected virtual void OnBorderStyleChanged (EventArgs e)
1339 EventHandler eh = (EventHandler)(Events [BorderStyleChangedEvent]);
1344 protected virtual void OnCaptionVisibleChanged (EventArgs e)
1346 EventHandler eh = (EventHandler)(Events [CaptionVisibleChangedEvent]);
1351 protected virtual void OnCurrentCellChanged (EventArgs e)
1353 EventHandler eh = (EventHandler)(Events [CurrentCellChangedEvent]);
1358 protected virtual void OnDataSourceChanged (EventArgs e)
1360 EventHandler eh = (EventHandler)(Events [DataSourceChangedEvent]);
1365 protected override void OnEnter (EventArgs e)
1371 protected virtual void OnFlatModeChanged (EventArgs e)
1373 EventHandler eh = (EventHandler)(Events [FlatModeChangedEvent]);
1378 protected override void OnFontChanged (EventArgs e)
1381 base.OnFontChanged (e);
1384 protected override void OnForeColorChanged (EventArgs e)
1386 base.OnForeColorChanged (e);
1389 protected override void OnHandleCreated (EventArgs e)
1391 base.OnHandleCreated (e);
1392 SetDataSource (datasource, datamember);
1395 protected override void OnHandleDestroyed (EventArgs e)
1397 base.OnHandleDestroyed (e);
1400 protected override void OnKeyDown (KeyEventArgs ke)
1402 base.OnKeyDown (ke);
1404 if (ProcessGridKey (ke) == true)
1407 /* TODO: we probably don't need this check,
1408 * since current_cell wouldn't have been set
1409 * to something invalid */
1410 if (CurrentTableStyle.GridColumnStyles.Count > 0) {
1411 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].OnKeyDown
1412 (ke, current_cell.RowNumber, current_cell.ColumnNumber);
1416 protected override void OnKeyPress (KeyPressEventArgs kpe)
1418 base.OnKeyPress (kpe);
1421 protected override void OnLayout (LayoutEventArgs levent)
1423 base.OnLayout (levent);
1424 CalcAreasAndInvalidate ();
1427 protected override void OnLeave (EventArgs e)
1432 if (cursor_in_add_row) {
1433 ListManager.CancelCurrentEdit ();
1437 protected override void OnMouseDown (MouseEventArgs e)
1439 base.OnMouseDown (e);
1441 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1442 bool shift_pressed = ((Control.ModifierKeys & Keys.Shift) != 0);
1444 HitTestInfo testinfo;
1445 testinfo = HitTest (e.X, e.Y);
1447 switch (testinfo.Type) {
1448 case HitTestType.Cell:
1449 if (testinfo.Row < 0 || testinfo.Column < 0)
1452 if (rows[testinfo.Row].IsExpanded) {
1453 Rectangle relation_area = rows[testinfo.Row].relation_area;
1454 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1455 if (relation_area.Contains (e.X, e.Y)) {
1456 /* the click happened in the relation area, navigate to the new table */
1457 int relative = e.Y - relation_area.Y;
1458 NavigateTo (testinfo.Row, CurrentTableStyle.Relations[relative / LinkFont.Height]);
1463 DataGridCell new_cell = new DataGridCell (testinfo.Row, testinfo.Column);
1465 if ((new_cell.Equals (current_cell) == false) || (!is_editing)) {
1466 CurrentCell = new_cell;
1469 CurrentTableStyle.GridColumnStyles[testinfo.Column].OnMouseDown (e, testinfo.Row, testinfo.Column);
1474 case HitTestType.RowHeader:
1475 bool expansion_click = false;
1476 if (CurrentTableStyle.HasRelations) {
1477 if (e.X > row_headers_area.X + row_headers_area.Width / 2) {
1478 /* it's in the +/- space */
1479 if (IsExpanded (testinfo.Row))
1480 Collapse (testinfo.Row);
1482 Expand (testinfo.Row);
1484 expansion_click = true;
1489 CurrentRow = testinfo.Row;
1491 if (!ctrl_pressed && !shift_pressed && !expansion_click) {
1492 ResetSelection (); // Invalidates selected rows
1495 if ((shift_pressed || expansion_click) && selection_start != -1) {
1496 ShiftSelection (testinfo.Row);
1497 } else { // ctrl_pressed or single item
1498 selection_start = testinfo.Row;
1499 Select (testinfo.Row);
1502 OnRowHeaderClick (EventArgs.Empty);
1506 case HitTestType.ColumnHeader:
1507 if (CurrentTableStyle.GridColumnStyles.Count == 0)
1510 if (AllowSorting == false)
1513 if (ListManager.List is IBindingList == false)
1516 ListSortDirection direction = ListSortDirection.Ascending;
1517 PropertyDescriptor prop = CurrentTableStyle.GridColumnStyles[testinfo.Column].PropertyDescriptor;
1518 IBindingList list = (IBindingList) ListManager.List;
1520 if (list.SortProperty != null) {
1521 CurrentTableStyle.GridColumnStyles[list.SortProperty].ArrowDrawingMode
1522 = DataGridColumnStyle.ArrowDrawing.No;
1525 if (prop == list.SortProperty && list.SortDirection == ListSortDirection.Ascending) {
1526 direction = ListSortDirection.Descending;
1529 CurrentTableStyle.GridColumnStyles[testinfo.Column].ArrowDrawingMode =
1530 direction == ListSortDirection.Ascending ?
1531 DataGridColumnStyle.ArrowDrawing.Ascending : DataGridColumnStyle.ArrowDrawing.Descending;
1533 list.ApplySort (prop, direction);
1537 case HitTestType.ColumnResize:
1538 if (e.Clicks == 2) {
1540 ColumnResize (testinfo.Column);
1542 resize_column = testinfo.Column;
1543 column_resize_active = true;
1544 resize_column_x = e.X;
1545 resize_column_width_delta = 0;
1547 DrawResizeLineVert (resize_column_x);
1551 case HitTestType.RowResize:
1552 if (e.Clicks == 2) {
1554 RowResize (testinfo.Row);
1556 resize_row = testinfo.Row;
1557 row_resize_active = true;
1559 resize_row_height_delta = 0;
1561 DrawResizeLineHoriz (resize_row_y);
1565 case HitTestType.Caption:
1566 if (back_button_rect.Contains (e.X, e.Y)) {
1567 back_button_active = true;
1568 Invalidate (back_button_rect);
1570 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1571 parent_rows_button_active = true;
1572 Invalidate (parent_rows_button_rect);
1581 protected override void OnMouseLeave (EventArgs e)
1583 base.OnMouseLeave (e);
1586 protected override void OnMouseMove (MouseEventArgs e)
1588 base.OnMouseMove (e);
1590 if (column_resize_active) {
1591 /* erase the old line */
1592 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1594 resize_column_width_delta = e.X - resize_column_x;
1596 /* draw the new line */
1597 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1600 else if (row_resize_active) {
1601 /* erase the old line */
1602 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1604 resize_row_height_delta = e.Y - resize_row_y;
1606 /* draw the new line */
1607 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1611 /* determine the cursor to use */
1612 HitTestInfo testinfo;
1613 testinfo = HitTest (e.X, e.Y);
1615 switch (testinfo.Type) {
1616 case HitTestType.ColumnResize:
1617 Cursor = Cursors.VSplit;
1619 case HitTestType.RowResize:
1620 Cursor = Cursors.HSplit;
1622 case HitTestType.Caption:
1623 Cursor = Cursors.Default;
1624 if (back_button_rect.Contains (e.X, e.Y)) {
1625 if (!back_button_mouseover)
1626 Invalidate (back_button_rect);
1627 back_button_mouseover = true;
1628 } else if (back_button_mouseover) {
1629 Invalidate (back_button_rect);
1630 back_button_mouseover = false;
1633 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1634 if (parent_rows_button_mouseover)
1635 Invalidate (parent_rows_button_rect);
1636 parent_rows_button_mouseover = true;
1637 } else if (parent_rows_button_mouseover) {
1638 Invalidate (parent_rows_button_rect);
1639 parent_rows_button_mouseover = false;
1642 case HitTestType.Cell:
1643 if (rows[testinfo.Row].IsExpanded) {
1644 Rectangle relation_area = rows[testinfo.Row].relation_area;
1645 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1646 if (relation_area.Contains (e.X, e.Y)) {
1647 Cursor = Cursors.Hand;
1652 Cursor = Cursors.Default;
1655 Cursor = Cursors.Default;
1661 protected override void OnMouseUp (MouseEventArgs e)
1665 if (column_resize_active) {
1666 column_resize_active = false;
1667 if (resize_column_width_delta + CurrentTableStyle.GridColumnStyles[resize_column].Width < 0)
1668 resize_column_width_delta = -CurrentTableStyle.GridColumnStyles[resize_column].Width;
1669 CurrentTableStyle.GridColumnStyles[resize_column].Width += resize_column_width_delta;
1670 width_of_all_columns += resize_column_width_delta;
1673 } else if (row_resize_active) {
1674 row_resize_active = false;
1676 if (resize_row_height_delta + rows[resize_row].Height < 0)
1677 resize_row_height_delta = -rows[resize_row].Height;
1679 rows[resize_row].height = rows[resize_row].Height + resize_row_height_delta;
1680 for (int i = resize_row + 1; i < rows.Length; i ++)
1681 rows[i].VerticalOffset += resize_row_height_delta;
1684 CalcAreasAndInvalidate ();
1685 } else if (back_button_active) {
1686 if (back_button_rect.Contains (e.X, e.Y)) {
1687 Invalidate (back_button_rect);
1689 OnBackButtonClicked (this, EventArgs.Empty);
1691 back_button_active = false;
1692 } else if (parent_rows_button_active) {
1693 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1694 Invalidate (parent_rows_button_rect);
1695 ParentRowsVisible = !ParentRowsVisible;
1696 OnShowParentDetailsButtonClicked (this, EventArgs.Empty);
1698 parent_rows_button_active = false;
1702 protected override void OnMouseWheel (MouseEventArgs e)
1704 base.OnMouseWheel (e);
1706 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1709 if (ctrl_pressed) { // scroll horizontally
1710 if (!horiz_scrollbar.Visible)
1715 pixels = Math.Max (horiz_scrollbar.Minimum,
1716 horiz_scrollbar.Value - horiz_scrollbar.LargeChange);
1719 pixels = Math.Min (horiz_scrollbar.Maximum - horiz_scrollbar.LargeChange + 1,
1720 horiz_scrollbar.Value + horiz_scrollbar.LargeChange);
1723 GridHScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1724 horiz_scrollbar.Value = pixels;
1726 if (!vert_scrollbar.Visible)
1731 pixels = Math.Max (vert_scrollbar.Minimum,
1732 vert_scrollbar.Value - vert_scrollbar.LargeChange);
1735 pixels = Math.Min (vert_scrollbar.Maximum - vert_scrollbar.LargeChange + 1,
1736 vert_scrollbar.Value + vert_scrollbar.LargeChange);
1739 GridVScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1740 vert_scrollbar.Value = pixels;
1744 protected void OnNavigate (NavigateEventArgs e)
1746 EventHandler eh = (EventHandler)(Events [NavigateEvent]);
1751 protected override void OnPaint (PaintEventArgs pe)
1753 ThemeEngine.Current.DataGridPaint (pe, this);
1756 protected override void OnPaintBackground (PaintEventArgs ebe)
1760 protected virtual void OnParentRowsLabelStyleChanged (EventArgs e)
1762 EventHandler eh = (EventHandler)(Events [ParentRowsLabelStyleChangedEvent]);
1767 protected virtual void OnParentRowsVisibleChanged (EventArgs e)
1769 EventHandler eh = (EventHandler)(Events [ParentRowsVisibleChangedEvent]);
1774 protected virtual void OnReadOnlyChanged (EventArgs e)
1776 EventHandler eh = (EventHandler)(Events [ReadOnlyChangedEvent]);
1781 protected override void OnResize (EventArgs e)
1786 protected void OnRowHeaderClick (EventArgs e)
1788 EventHandler eh = (EventHandler)(Events [RowHeaderClickEvent]);
1793 protected void OnScroll (EventArgs e)
1795 EventHandler eh = (EventHandler)(Events [ScrollEvent]);
1800 protected void OnShowParentDetailsButtonClicked (object sender, EventArgs e)
1802 EventHandler eh = (EventHandler)(Events [ShowParentDetailsButtonClickEvent]);
1807 protected override bool ProcessDialogKey (Keys keyData)
1809 return ProcessGridKey (new KeyEventArgs (keyData));
1812 void UpdateSelectionAfterCursorMove (bool extend_selection)
1814 if (extend_selection) {
1816 ShiftSelection (CurrentRow);
1819 selection_start = CurrentRow;
1823 protected bool ProcessGridKey (KeyEventArgs ke)
1825 bool ctrl_pressed = ((ke.Modifiers & Keys.Control) != 0);
1826 //bool alt_pressed = ((ke.Modifiers & Keys.Alt) != 0);
1827 bool shift_pressed = ((ke.Modifiers & Keys.Shift) != 0);
1829 switch (ke.KeyCode) {
1841 CurrentTableStyle.GridColumnStyles[CurrentColumn].EnterNullValue ();
1852 if (shift_pressed) {
1853 if (CurrentColumn > 0)
1855 else if ((CurrentRow > 0) && (CurrentColumn == 0))
1856 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1858 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1)
1860 else if ((CurrentRow <= RowsCount) && (CurrentColumn == CurrentTableStyle.GridColumnStyles.Count - 1))
1861 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1864 UpdateSelectionAfterCursorMove (false);
1870 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1872 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1) {
1874 } else if (CurrentRow < RowsCount - 1
1875 || (CurrentRow == RowsCount - 1
1876 && !cursor_in_add_row)) {
1877 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1881 UpdateSelectionAfterCursorMove (false);
1889 if (current_cell.ColumnNumber > 0)
1891 else if (CurrentRow > 0)
1892 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1895 UpdateSelectionAfterCursorMove (false);
1902 else if (CurrentRow > 0)
1905 UpdateSelectionAfterCursorMove (shift_pressed);
1911 CurrentRow = RowsCount - 1;
1912 else if (CurrentRow < RowsCount - 1)
1914 else if (CurrentRow == RowsCount - 1 && cursor_in_add_row && (add_row_changed || is_changing))
1916 else if (CurrentRow == RowsCount - 1 && !cursor_in_add_row && !shift_pressed)
1919 UpdateSelectionAfterCursorMove (shift_pressed);
1924 if (CurrentRow > VLargeChange)
1925 CurrentRow -= VLargeChange;
1929 UpdateSelectionAfterCursorMove (shift_pressed);
1934 if (CurrentRow < RowsCount - VLargeChange)
1935 CurrentRow += VLargeChange;
1937 CurrentRow = RowsCount - 1;
1939 UpdateSelectionAfterCursorMove (shift_pressed);
1945 CurrentCell = new DataGridCell (0, 0);
1949 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1955 CurrentCell = new DataGridCell (RowsCount - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1957 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1959 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1966 else if (selected_rows.Keys.Count > 0) {
1967 foreach (int row in selected_rows.Keys)
1968 ListManager.RemoveAt (row);
1969 selected_rows.Clear ();
1970 CalcAreasAndInvalidate ();
1976 return false; // message not processed
1979 protected override bool ProcessKeyPreview (ref Message m)
1981 if ((Msg) m.Msg == Msg.WM_KEYDOWN) {
1982 Keys key = (Keys) m.WParam.ToInt32 ();
1983 KeyEventArgs ke = new KeyEventArgs (key);
1984 if (ProcessGridKey (ke))
1988 return base.ProcessKeyPreview (ref m);
1991 protected bool ProcessTabKey (Keys keyData)
1996 public void ResetAlternatingBackColor ()
1998 grid_style.AlternatingBackColor = default_style.AlternatingBackColor;
2001 public override void ResetBackColor ()
2003 grid_style.BackColor = default_style.BackColor;
2006 public override void ResetForeColor ()
2008 grid_style.ForeColor = default_style.ForeColor;
2011 public void ResetGridLineColor ()
2013 grid_style.GridLineColor = default_style.GridLineColor;
2016 public void ResetHeaderBackColor ()
2018 grid_style.HeaderBackColor = default_style.HeaderBackColor;
2021 public void ResetHeaderFont ()
2023 grid_style.HeaderFont = null;
2026 public void ResetHeaderForeColor ()
2028 grid_style.HeaderForeColor = default_style.HeaderForeColor;
2031 public void ResetLinkColor ()
2033 grid_style.LinkColor = default_style.LinkColor;
2036 public void ResetLinkHoverColor ()
2038 grid_style.LinkHoverColor = default_style.LinkHoverColor;
2041 protected void ResetSelection ()
2043 InvalidateSelection ();
2044 selected_rows.Clear ();
2045 selection_start = -1;
2048 void InvalidateSelection ()
2050 foreach (int row in selected_rows.Keys) {
2051 rows[row].IsSelected = false;
2052 InvalidateRow (row);
2056 public void ResetSelectionBackColor ()
2058 grid_style.SelectionBackColor = default_style.SelectionBackColor;
2061 public void ResetSelectionForeColor ()
2063 grid_style.SelectionForeColor = default_style.SelectionForeColor;
2066 public void Select (int row)
2070 if (selected_rows.Count == 0)
2071 selection_start = row;
2073 selected_rows[row] = true;
2074 rows[row].IsSelected = true;
2076 InvalidateRow (row);
2079 public void SetDataBinding (object dataSource, string dataMember)
2081 SetDataSource (dataSource, dataMember);
2084 protected virtual bool ShouldSerializeAlternatingBackColor ()
2086 return (grid_style.AlternatingBackColor != default_style.AlternatingBackColor);
2089 protected virtual bool ShouldSerializeBackgroundColor ()
2091 return (background_color != def_background_color);
2094 protected virtual bool ShouldSerializeCaptionBackColor ()
2096 return (caption_backcolor != def_caption_backcolor);
2099 protected virtual bool ShouldSerializeCaptionForeColor ()
2101 return caption_forecolor != def_caption_forecolor;
2104 protected virtual bool ShouldSerializeGridLineColor ()
2106 return grid_style.GridLineColor != default_style.GridLineColor;
2109 protected virtual bool ShouldSerializeHeaderBackColor ()
2111 return grid_style.HeaderBackColor != default_style.HeaderBackColor;
2114 protected bool ShouldSerializeHeaderFont ()
2116 return grid_style.HeaderFont != default_style.HeaderFont;
2119 protected virtual bool ShouldSerializeHeaderForeColor ()
2121 return grid_style.HeaderForeColor != default_style.HeaderForeColor;
2124 protected virtual bool ShouldSerializeLinkHoverColor ()
2126 return grid_style.LinkHoverColor != grid_style.LinkHoverColor;
2129 protected virtual bool ShouldSerializeParentRowsBackColor ()
2131 return parent_rows_backcolor != def_parent_rows_backcolor;
2134 protected virtual bool ShouldSerializeParentRowsForeColor ()
2136 return parent_rows_backcolor != def_parent_rows_backcolor;
2139 protected bool ShouldSerializePreferredRowHeight ()
2141 return grid_style.PreferredRowHeight != default_style.PreferredRowHeight;
2144 protected bool ShouldSerializeSelectionBackColor ()
2146 return grid_style.SelectionBackColor != default_style.SelectionBackColor;
2149 protected virtual bool ShouldSerializeSelectionForeColor ()
2151 return grid_style.SelectionForeColor != default_style.SelectionForeColor;
2154 public void SubObjectsSiteChange (bool site)
2158 public void UnSelect (int row)
2160 rows[row].IsSelected = false;
2161 selected_rows.Remove (row);
2162 InvalidateRow (row);
2164 #endregion // Public Instance Methods
2166 #region Private Instance Methods
2168 internal void CalcAreasAndInvalidate ()
2174 private void ConnectListManagerEvents ()
2176 list_manager.MetaDataChanged += new EventHandler (OnListManagerMetaDataChanged);
2177 list_manager.PositionChanged += new EventHandler (OnListManagerPositionChanged);
2178 list_manager.ItemChanged += new ItemChangedEventHandler (OnListManagerItemChanged);
2181 private void DisconnectListManagerEvents ()
2183 list_manager.MetaDataChanged -= new EventHandler (OnListManagerMetaDataChanged);
2184 list_manager.PositionChanged -= new EventHandler (OnListManagerPositionChanged);
2185 list_manager.ItemChanged -= new ItemChangedEventHandler (OnListManagerItemChanged);
2188 void DisconnectTableStyleEvents ()
2190 current_style.AllowSortingChanged -= new EventHandler (TableStyleChanged);
2191 current_style.AlternatingBackColorChanged -= new EventHandler (TableStyleChanged);
2192 current_style.BackColorChanged -= new EventHandler (TableStyleChanged);
2193 current_style.ColumnHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2194 current_style.ForeColorChanged -= new EventHandler (TableStyleChanged);
2195 current_style.GridLineColorChanged -= new EventHandler (TableStyleChanged);
2196 current_style.GridLineStyleChanged -= new EventHandler (TableStyleChanged);
2197 current_style.HeaderBackColorChanged -= new EventHandler (TableStyleChanged);
2198 current_style.HeaderFontChanged -= new EventHandler (TableStyleChanged);
2199 current_style.HeaderForeColorChanged -= new EventHandler (TableStyleChanged);
2200 current_style.LinkColorChanged -= new EventHandler (TableStyleChanged);
2201 current_style.LinkHoverColorChanged -= new EventHandler (TableStyleChanged);
2202 current_style.MappingNameChanged -= new EventHandler (TableStyleChanged);
2203 current_style.PreferredColumnWidthChanged -= new EventHandler (TableStyleChanged);
2204 current_style.PreferredRowHeightChanged -= new EventHandler (TableStyleChanged);
2205 current_style.ReadOnlyChanged -= new EventHandler (TableStyleChanged);
2206 current_style.RowHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2207 current_style.RowHeaderWidthChanged -= new EventHandler (TableStyleChanged);
2208 current_style.SelectionBackColorChanged -= new EventHandler (TableStyleChanged);
2209 current_style.SelectionForeColorChanged -= new EventHandler (TableStyleChanged);
2212 void ConnectTableStyleEvents ()
2214 current_style.AllowSortingChanged += new EventHandler (TableStyleChanged);
2215 current_style.AlternatingBackColorChanged += new EventHandler (TableStyleChanged);
2216 current_style.BackColorChanged += new EventHandler (TableStyleChanged);
2217 current_style.ColumnHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2218 current_style.ForeColorChanged += new EventHandler (TableStyleChanged);
2219 current_style.GridLineColorChanged += new EventHandler (TableStyleChanged);
2220 current_style.GridLineStyleChanged += new EventHandler (TableStyleChanged);
2221 current_style.HeaderBackColorChanged += new EventHandler (TableStyleChanged);
2222 current_style.HeaderFontChanged += new EventHandler (TableStyleChanged);
2223 current_style.HeaderForeColorChanged += new EventHandler (TableStyleChanged);
2224 current_style.LinkColorChanged += new EventHandler (TableStyleChanged);
2225 current_style.LinkHoverColorChanged += new EventHandler (TableStyleChanged);
2226 current_style.MappingNameChanged += new EventHandler (TableStyleChanged);
2227 current_style.PreferredColumnWidthChanged += new EventHandler (TableStyleChanged);
2228 current_style.PreferredRowHeightChanged += new EventHandler (TableStyleChanged);
2229 current_style.ReadOnlyChanged += new EventHandler (TableStyleChanged);
2230 current_style.RowHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2231 current_style.RowHeaderWidthChanged += new EventHandler (TableStyleChanged);
2232 current_style.SelectionBackColorChanged += new EventHandler (TableStyleChanged);
2233 current_style.SelectionForeColorChanged += new EventHandler (TableStyleChanged);
2236 void TableStyleChanged (object sender, EventArgs args)
2239 CalcAreasAndInvalidate ();
2243 private void EnsureCellVisibility (DataGridCell cell)
2245 if (cell.ColumnNumber <= first_visible_column ||
2246 cell.ColumnNumber + 1 >= first_visible_column + visible_column_count) {
2248 first_visible_column = GetFirstColumnForColumnVisibility (first_visible_column, cell.ColumnNumber);
2249 int pixel = GetColumnStartingPixel (first_visible_column);
2250 ScrollToColumnInPixels (pixel);
2251 horiz_scrollbar.Value = pixel;
2255 if (cell.RowNumber < first_visible_row ||
2256 cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2258 if (cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2259 int old_first_visible_row = first_visible_row;
2260 first_visible_row = 1 + cell.RowNumber - visible_row_count;
2261 UpdateVisibleRowCount ();
2262 ScrollToRow (old_first_visible_row, first_visible_row);
2264 int old_first_visible_row = first_visible_row;
2265 first_visible_row = cell.RowNumber;
2266 UpdateVisibleRowCount ();
2267 ScrollToRow (old_first_visible_row, first_visible_row);
2270 vert_scrollbar.Value = first_visible_row;
2274 private void SetDataSource (object source, string member)
2276 SetDataSource (source, member, true);
2279 bool in_setdatasource;
2280 private void SetDataSource (object source, string member, bool recreate_rows)
2282 CurrencyManager old_lm = list_manager;
2284 /* we need this bool flag to work around a
2285 * problem with OnBindingContextChanged. once
2286 * that stuff works properly, remove this
2288 if (in_setdatasource)
2290 in_setdatasource = true;
2293 if (datasource == source && member == datamember)
2297 if (source != null && source as IListSource != null && source as IList != null)
2298 throw new Exception ("Wrong complex data binding source");
2300 datasource = source;
2301 datamember = member;
2306 current_cell = new DataGridCell ();
2308 if (list_manager != null)
2309 DisconnectListManagerEvents ();
2311 list_manager = null;
2313 /* create the new list manager */
2314 if (BindingContext != null && datasource != null)
2315 list_manager = (CurrencyManager) BindingContext [datasource, datamember];
2317 if (list_manager != null)
2318 ConnectListManagerEvents ();
2320 if (old_lm != list_manager) {
2323 /* reset first_visible_row to 0 here before
2324 * doing anything that'll requires us to
2325 * figure out if we need a scrollbar. */
2326 vert_scrollbar.Value = 0;
2327 horiz_scrollbar.Value = 0;
2328 first_visible_row = 0;
2331 RecreateDataGridRows (false);
2334 CalcAreasAndInvalidate ();
2336 in_setdatasource = false;
2338 OnDataSourceChanged (EventArgs.Empty);
2341 void RecreateDataGridRows (bool recalc)
2343 DataGridRelationshipRow[] new_rows = new DataGridRelationshipRow[RowsCount + (ShowEditRow ? 1 : 0)];
2344 int start_index = 0;
2346 start_index = rows.Length;
2347 Array.Copy (rows, 0, new_rows, 0, rows.Length < new_rows.Length ? rows.Length : new_rows.Length);
2350 for (int i = start_index; i < new_rows.Length; i ++) {
2351 new_rows[i] = new DataGridRelationshipRow (this);
2352 new_rows[i].height = RowHeight;
2354 new_rows[i].VerticalOffset = new_rows[i-1].VerticalOffset + new_rows[i-1].Height;
2360 CalcAreasAndInvalidate ();
2363 internal void UpdateRowsFrom (DataGridRelationshipRow row)
2365 int start_index = Array.IndexOf (rows, row);
2366 if (start_index == -1)
2369 for (int i = start_index + 1; i < rows.Length; i ++)
2370 rows[i].VerticalOffset = rows[i-1].VerticalOffset + rows[i-1].Height;
2372 CalcAreasAndInvalidate ();
2377 if (list_manager != null) {
2378 string list_name = list_manager.GetListName (null);
2379 if (TableStyles[list_name] == null) {
2380 // no style exists by the supplied name
2381 current_style.GridColumnStyles.Clear ();
2382 current_style.CreateColumnsForTable (false);
2383 } else if (CurrentTableStyle == grid_style ||
2384 CurrentTableStyle.MappingName != list_name) {
2385 // If the style has been defined by the user, use it
2386 CurrentTableStyle = styles_collection[list_name];
2387 current_style.CreateColumnsForTable (true);
2389 current_style.CreateColumnsForTable (true);
2392 current_style.CreateColumnsForTable (false);
2395 private void OnListManagerMetaDataChanged (object sender, EventArgs e)
2399 //we need to rethink this, as in 2.0 we get this event when a column is added to a table.
2400 // forcing a rebind of columns means that we fail bug #80422. disable this for now.
2405 private void OnListManagerPositionChanged (object sender, EventArgs e)
2407 from_positionchanged_handler = true;
2408 CurrentRow = list_manager.Position;
2409 from_positionchanged_handler = false;
2412 private void OnListManagerItemChanged (object sender, ItemChangedEventArgs e)
2414 if (e.Index == -1) {
2416 if (rows == null || RowsCount != rows.Length - (ShowEditRow ? 1 : 0))
2417 RecreateDataGridRows (true);
2419 InvalidateRow (e.Index);
2423 private void OnTableStylesCollectionChanged (object sender, CollectionChangeEventArgs e)
2425 if (ListManager == null)
2428 string list_name = ListManager.GetListName (null);
2430 case CollectionChangeAction.Add:
2431 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2432 CurrentTableStyle = (DataGridTableStyle)e.Element;
2433 ((DataGridTableStyle) e.Element).CreateColumnsForTable (false);
2436 case CollectionChangeAction.Remove:
2437 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2438 CurrentTableStyle = default_style;
2439 current_style.GridColumnStyles.Clear ();
2440 current_style.CreateColumnsForTable (false);
2443 case CollectionChangeAction.Refresh:
2444 if (CurrentTableStyle == default_style
2445 || String.Compare (list_name, CurrentTableStyle.MappingName, true) != 0) {
2446 DataGridTableStyle style = styles_collection [list_name];
2447 if (style != null) {
2448 CurrentTableStyle = style;
2449 current_style.CreateColumnsForTable (false);
2451 CurrentTableStyle = default_style;
2452 current_style.GridColumnStyles.Clear ();
2453 current_style.CreateColumnsForTable (false);
2458 CalcAreasAndInvalidate ();
2461 private void AddNewRow ()
2463 ListManager.EndCurrentEdit ();
2464 ListManager.AddNew ();
2467 private void Edit ()
2469 if (CurrentTableStyle.GridColumnStyles.Count == 0)
2472 if (!CurrentTableStyle.GridColumnStyles[CurrentColumn].bound)
2476 is_changing = false;
2478 CurrentTableStyle.GridColumnStyles[CurrentColumn].Edit (ListManager,
2479 CurrentRow, GetCellBounds (CurrentRow, CurrentColumn),
2480 _readonly, null, true);
2483 private void EndEdit ()
2485 if (CurrentTableStyle.GridColumnStyles.Count == 0)
2488 if (!CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].bound)
2491 EndEdit (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber],
2492 current_cell.RowNumber, false);
2495 private void ShiftSelection (int index)
2497 // we have to save off selection_start
2498 // because ResetSelection clobbers it
2499 int saved_selection_start = selection_start;
2503 selection_start = saved_selection_start;
2505 if (index >= selection_start) {
2506 start = selection_start;
2510 end = selection_start;
2513 if (start == -1) start = 0;
2515 for (int idx = start; idx <= end; idx ++)
2519 private void ScrollToColumnInPixels (int pixel)
2523 if (pixel > horiz_pixeloffset) // ScrollRight
2524 pixels = -1 * (pixel - horiz_pixeloffset);
2526 pixels = horiz_pixeloffset - pixel;
2528 Rectangle area = cells_area;
2530 if (ColumnHeadersVisible) {
2531 area.Y -= ColumnHeadersArea.Height;
2532 area.Height += ColumnHeadersArea.Height;
2535 horiz_pixeloffset = pixel;
2536 UpdateVisibleColumn ();
2540 XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
2542 int pixel_offset = GetColumnStartingPixel (CurrentColumn);
2543 int next_pixel_offset = pixel_offset + CurrentTableStyle.GridColumnStyles[CurrentColumn].Width;
2545 if (pixel_offset >= horiz_pixeloffset
2546 && next_pixel_offset < horiz_pixeloffset + cells_area.Width)
2550 private void ScrollToRow (int old_row, int new_row)
2555 if (new_row > old_row) { // Scrolldown
2556 for (i = old_row; i < new_row; i ++)
2557 pixels -= rows[i].Height;
2559 for (i = new_row; i < old_row; i ++)
2560 pixels += rows[i].Height;
2568 Rectangle rows_area = cells_area; // Cells area - partial rows space
2570 if (RowHeadersVisible) {
2571 rows_area.X -= RowHeaderWidth;
2572 rows_area.Width += RowHeaderWidth;
2575 /* scroll the window */
2576 XplatUI.ScrollWindow (Handle, rows_area, 0, pixels, false);
2578 /* if the row is still */
2579 if (CurrentRow >= first_visible_row && CurrentRow < first_visible_row + visible_row_count)
2584 private void ColumnResize (int column)
2586 CurrencyManager source = this.ListManager;
2587 DataGridColumnStyle style = CurrentTableStyle.GridColumnStyles[column];
2588 string headerText = style.HeaderText;
2589 using (Graphics g = base.CreateGraphics ()) {
2590 int rows = source.Count;
2591 int width = (int)g.MeasureString (headerText, CurrentTableStyle.HeaderFont).Width + 4;
2593 for (int i = 0; i < rows; i++) {
2594 int rowColWidth = (int)style.GetPreferredSize (g, style.GetColumnValueAtRow (source, i)).Width;
2595 if (rowColWidth > width)
2596 width = rowColWidth;
2598 if (style.Width != width)
2599 style.Width = width;
2603 private void RowResize (int row)
2605 CurrencyManager source = this.ListManager;
2606 using (Graphics g = base.CreateGraphics ()) {
2607 GridColumnStylesCollection columns = CurrentTableStyle.GridColumnStyles;
2608 int colCount = columns.Count;
2609 //int rowCount = source.Count;
2611 for (int i = 0; i < colCount; i++) {
2612 object val = columns[i].GetColumnValueAtRow (source, row);
2613 height = Math.Max (columns[i].GetPreferredHeight (g, val), height);
2615 if (this.DataGridRows[row].Height != height)
2616 this.DataGridRows[row].Height = height;
2619 #endregion Private Instance Methods
2622 static object AllowNavigationChangedEvent = new object ();
2623 static object BackButtonClickEvent = new object ();
2624 static object BackgroundColorChangedEvent = new object ();
2625 static object BorderStyleChangedEvent = new object ();
2626 static object CaptionVisibleChangedEvent = new object ();
2627 static object CurrentCellChangedEvent = new object ();
2628 static object DataSourceChangedEvent = new object ();
2629 static object FlatModeChangedEvent = new object ();
2630 static object NavigateEvent = new object ();
2631 static object ParentRowsLabelStyleChangedEvent = new object ();
2632 static object ParentRowsVisibleChangedEvent = new object ();
2633 static object ReadOnlyChangedEvent = new object ();
2634 static object RowHeaderClickEvent = new object ();
2635 static object ScrollEvent = new object ();
2636 static object ShowParentDetailsButtonClickEvent = new object ();
2638 public event EventHandler AllowNavigationChanged {
2639 add { Events.AddHandler (AllowNavigationChangedEvent, value); }
2640 remove { Events.RemoveHandler (AllowNavigationChangedEvent, value); }
2643 public event EventHandler BackButtonClick {
2644 add { Events.AddHandler (BackButtonClickEvent, value); }
2645 remove { Events.RemoveHandler (BackButtonClickEvent, value); }
2648 public event EventHandler BackgroundColorChanged {
2649 add { Events.AddHandler (BackgroundColorChangedEvent, value); }
2650 remove { Events.RemoveHandler (BackgroundColorChangedEvent, value); }
2654 [EditorBrowsable(EditorBrowsableState.Never)]
2655 public new event EventHandler BackgroundImageChanged {
2656 add { base.BackgroundImageChanged += value; }
2657 remove { base.BackgroundImageChanged -= value; }
2662 [EditorBrowsable(EditorBrowsableState.Never)]
2663 public new event EventHandler BackgroundImageLayoutChanged {
2664 add { base.BackgroundImageLayoutChanged += value; }
2665 remove { base.BackgroundImageLayoutChanged -= value; }
2670 [EditorBrowsable(EditorBrowsableState.Never)]
2671 public new event EventHandler TextChanged {
2672 add { base.TextChanged += value; }
2673 remove { base.TextChanged -= value; }
2677 [EditorBrowsable(EditorBrowsableState.Never)]
2678 public new event EventHandler CursorChanged {
2679 add { base.CursorChanged += value; }
2680 remove { base.CursorChanged -= value; }
2683 public event EventHandler BorderStyleChanged {
2684 add { Events.AddHandler (BorderStyleChangedEvent, value); }
2685 remove { Events.RemoveHandler (BorderStyleChangedEvent, value); }
2688 public event EventHandler CaptionVisibleChanged {
2689 add { Events.AddHandler (CaptionVisibleChangedEvent, value); }
2690 remove { Events.RemoveHandler (CaptionVisibleChangedEvent, value); }
2693 public event EventHandler CurrentCellChanged {
2694 add { Events.AddHandler (CurrentCellChangedEvent, value); }
2695 remove { Events.RemoveHandler (CurrentCellChangedEvent, value); }
2698 public event EventHandler DataSourceChanged {
2699 add { Events.AddHandler (DataSourceChangedEvent, value); }
2700 remove { Events.RemoveHandler (DataSourceChangedEvent, value); }
2703 public event EventHandler FlatModeChanged {
2704 add { Events.AddHandler (FlatModeChangedEvent, value); }
2705 remove { Events.RemoveHandler (FlatModeChangedEvent, value); }
2708 public event NavigateEventHandler Navigate {
2709 add { Events.AddHandler (NavigateEvent, value); }
2710 remove { Events.RemoveHandler (NavigateEvent, value); }
2713 public event EventHandler ParentRowsLabelStyleChanged {
2714 add { Events.AddHandler (ParentRowsLabelStyleChangedEvent, value); }
2715 remove { Events.RemoveHandler (ParentRowsLabelStyleChangedEvent, value); }
2718 public event EventHandler ParentRowsVisibleChanged {
2719 add { Events.AddHandler (ParentRowsVisibleChangedEvent, value); }
2720 remove { Events.RemoveHandler (ParentRowsVisibleChangedEvent, value); }
2723 public event EventHandler ReadOnlyChanged {
2724 add { Events.AddHandler (ReadOnlyChangedEvent, value); }
2725 remove { Events.RemoveHandler (ReadOnlyChangedEvent, value); }
2728 protected event EventHandler RowHeaderClick {
2729 add { Events.AddHandler (RowHeaderClickEvent, value); }
2730 remove { Events.RemoveHandler (RowHeaderClickEvent, value); }
2733 public event EventHandler Scroll {
2734 add { Events.AddHandler (ScrollEvent, value); }
2735 remove { Events.RemoveHandler (ScrollEvent, value); }
2738 public event EventHandler ShowParentDetailsButtonClick {
2739 add { Events.AddHandler (ShowParentDetailsButtonClickEvent, value); }
2740 remove { Events.RemoveHandler (ShowParentDetailsButtonClickEvent, value); }
2742 #endregion // Events
2744 #region Code originally in DataGridDrawingLogic.cs
2746 #region Local Variables
2749 Rectangle parent_rows;
2750 int width_of_all_columns;
2752 internal Rectangle caption_area;
2753 internal Rectangle column_headers_area; // Used columns header area
2754 internal int column_headers_max_width; // Total width (max width) for columns headrs
2755 internal Rectangle row_headers_area; // Used Headers rows area
2756 internal Rectangle cells_area;
2757 #endregion // Local Variables
2759 #region Public Instance Methods
2761 // Calc the max with of all columns
2762 int CalcAllColumnsWidth ()
2765 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2767 for (int col = 0; col < cnt; col++) {
2768 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2771 width += CurrentTableStyle.GridColumnStyles[col].Width;
2776 // Gets a column from a pixel
2777 int FromPixelToColumn (int pixel, out int column_x)
2780 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2786 if (CurrentTableStyle.CurrentRowHeadersVisible) {
2787 width += row_headers_area.X + row_headers_area.Width;
2788 column_x += row_headers_area.X + row_headers_area.Width;
2791 for (int col = 0; col < cnt; col++) {
2792 if (CurrentTableStyle.GridColumnStyles[col].bound == false)
2795 width += CurrentTableStyle.GridColumnStyles[col].Width;
2800 column_x += CurrentTableStyle.GridColumnStyles[col].Width;
2806 internal int GetColumnStartingPixel (int my_col)
2809 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2811 for (int col = 0; col < cnt; col++) {
2812 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2819 width += CurrentTableStyle.GridColumnStyles[col].Width;
2825 // Which column has to be the first visible column to ensure a column visibility
2826 int GetFirstColumnForColumnVisibility (int current_first_visible_column, int column)
2828 int new_col = column;
2831 if (column > current_first_visible_column) { // Going forward
2832 for (new_col = column; new_col >= 0; new_col--) {
2833 if (!CurrentTableStyle.GridColumnStyles[new_col].bound)
2835 width += CurrentTableStyle.GridColumnStyles[new_col].Width;
2837 if (width >= cells_area.Width)
2839 //return new_col < CurrentTableStyle.GridColumnStyles.Count ? new_col + 1 : CurrentTableStyle.GridColumnStyles.Count;
2847 bool in_calc_grid_areas;
2848 void CalcGridAreas ()
2850 if (!IsHandleCreated) // Delay calculations until the handle is created
2853 /* make sure we don't happen to end up in this method again */
2854 if (in_calc_grid_areas)
2857 in_calc_grid_areas = true;
2859 /* Order is important. E.g. row headers max. height depends on caption */
2860 horiz_pixeloffset = 0;
2863 CalcParentButtons ();
2864 UpdateVisibleRowCount ();
2866 width_of_all_columns = CalcAllColumnsWidth ();
2867 CalcColumnHeaders ();
2870 bool needHoriz = false;
2871 bool needVert = false;
2873 /* figure out which scrollbars we need, and what the visible areas are */
2874 int visible_cells_width = cells_area.Width;
2875 int visible_cells_height = cells_area.Height;
2876 int allrows = RowsCount;
2878 if (ShowEditRow && RowsCount > 0)
2881 /* use a loop to iteratively calculate whether
2882 * we need horiz/vert scrollbars. */
2883 for (int i = 0; i < 3; i++) {
2885 visible_cells_width = cells_area.Width - vert_scrollbar.Width;
2887 visible_cells_height = cells_area.Height - horiz_scrollbar.Height;
2889 UpdateVisibleRowCount ();
2891 needHoriz = (width_of_all_columns > visible_cells_width);
2892 needVert = (allrows > visible_row_count);
2895 int horiz_scrollbar_width = ClientRectangle.Width;
2896 int horiz_scrollbar_maximum = 0;
2897 int vert_scrollbar_height = 0;
2898 int vert_scrollbar_maximum = 0;
2901 SetUpVerticalScrollBar (out vert_scrollbar_height, out vert_scrollbar_maximum);
2904 SetUpHorizontalScrollBar (out horiz_scrollbar_maximum);
2906 cells_area.Width = visible_cells_width;
2907 cells_area.Height = visible_cells_height;
2909 if (needVert && needHoriz) {
2911 parent_rows.Width -= vert_scrollbar.Width;
2913 if (!ShowingColumnHeaders) {
2914 if (column_headers_area.X + column_headers_area.Width > vert_scrollbar.Location.X) {
2915 column_headers_area.Width -= vert_scrollbar.Width;
2919 horiz_scrollbar_width -= vert_scrollbar.Width;
2920 vert_scrollbar_height -= horiz_scrollbar.Height;
2924 if (row_headers_area.Y + row_headers_area.Height > ClientRectangle.Y + ClientRectangle.Height) {
2925 row_headers_area.Height -= horiz_scrollbar.Height;
2928 vert_scrollbar.Size = new Size (vert_scrollbar.Width,
2929 vert_scrollbar_height);
2931 vert_scrollbar.Maximum = vert_scrollbar_maximum;
2932 Controls.Add (vert_scrollbar);
2933 vert_scrollbar.Visible = true;
2935 Controls.Remove (vert_scrollbar);
2936 vert_scrollbar.Visible = false;
2940 horiz_scrollbar.Size = new Size (horiz_scrollbar_width,
2941 horiz_scrollbar.Height);
2943 horiz_scrollbar.Maximum = horiz_scrollbar_maximum;
2944 Controls.Add (horiz_scrollbar);
2945 horiz_scrollbar.Visible = true;
2947 Controls.Remove (horiz_scrollbar);
2948 horiz_scrollbar.Visible = false;
2951 UpdateVisibleColumn ();
2952 UpdateVisibleRowCount ();
2954 in_calc_grid_areas = false;
2959 caption_area.X = ClientRectangle.X;
2960 caption_area.Y = ClientRectangle.Y;
2961 caption_area.Width = ClientRectangle.Width;
2962 if (caption_visible) {
2963 caption_area.Height = CaptionFont.Height;
2964 if (caption_area.Height < back_button_image.Height)
2965 caption_area.Height = back_button_image.Height;
2966 caption_area.Height += 2;
2968 caption_area.Height = 0;
2971 void CalcCellsArea ()
2973 cells_area.X = ClientRectangle.X + row_headers_area.Width;
2974 cells_area.Y = column_headers_area.Y + column_headers_area.Height;
2975 cells_area.Width = ClientRectangle.X + ClientRectangle.Width - cells_area.X;
2976 if (cells_area.Width < 0)
2977 cells_area.Width = 0;
2978 cells_area.Height = ClientRectangle.Y + ClientRectangle.Height - cells_area.Y;
2979 if (cells_area.Height < 0)
2980 cells_area.Height = 0;
2983 void CalcColumnHeaders ()
2987 column_headers_area.X = ClientRectangle.X;
2988 column_headers_area.Y = parent_rows.Y + parent_rows.Height;
2990 // TODO: take into account Scrollbars
2991 column_headers_max_width = ClientRectangle.X + ClientRectangle.Width - column_headers_area.X;
2992 max_width_cols = column_headers_max_width;
2994 if (CurrentTableStyle.CurrentRowHeadersVisible)
2995 max_width_cols -= RowHeaderWidth;
2997 if (width_of_all_columns > max_width_cols) {
2998 column_headers_area.Width = column_headers_max_width;
3000 column_headers_area.Width = width_of_all_columns;
3002 if (CurrentTableStyle.CurrentRowHeadersVisible)
3003 column_headers_area.Width += RowHeaderWidth;
3006 if (ShowingColumnHeaders)
3007 column_headers_area.Height = CurrentTableStyle.HeaderFont.Height + 6;
3009 column_headers_area.Height = 0;
3012 void CalcParentRows ()
3014 parent_rows.X = ClientRectangle.X;
3015 parent_rows.Y = caption_area.Y + caption_area.Height;
3016 parent_rows.Width = ClientRectangle.Width;
3018 parent_rows.Height = (CaptionFont.Height + 3) * data_source_stack.Count;
3020 parent_rows.Height = 0;
3023 void CalcParentButtons ()
3025 if (data_source_stack.Count > 0 && CaptionVisible) {
3026 back_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - 2 * (caption_area.Height - 2) - 8,
3027 caption_area.Height / 2 - back_button_image.Height / 2,
3028 back_button_image.Width, back_button_image.Height);
3029 parent_rows_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - (caption_area.Height - 2) - 4,
3030 caption_area.Height / 2 - parent_rows_button_image.Height / 2,
3031 parent_rows_button_image.Width, parent_rows_button_image.Height);
3033 back_button_rect = parent_rows_button_rect = Rectangle.Empty;
3037 void CalcRowHeaders ()
3039 row_headers_area.X = ClientRectangle.X;
3040 row_headers_area.Y = column_headers_area.Y + column_headers_area.Height;
3041 row_headers_area.Height = ClientRectangle.Height + ClientRectangle.Y - row_headers_area.Y;
3043 if (CurrentTableStyle.CurrentRowHeadersVisible)
3044 row_headers_area.Width = RowHeaderWidth;
3046 row_headers_area.Width = 0;
3049 int GetVisibleRowCount (int visibleHeight)
3051 int rows_height = 0;
3053 for (r = FirstVisibleRow; r < rows.Length; r ++) {
3054 if (rows_height + rows[r].Height >= visibleHeight)
3056 rows_height += rows[r].Height;
3059 if (r <= rows.Length - 1)
3062 return r - FirstVisibleRow;
3065 void UpdateVisibleColumn ()
3067 if (CurrentTableStyle.GridColumnStyles.Count == 0) {
3068 visible_column_count = 0;
3073 int max_pixel = horiz_pixeloffset + cells_area.Width;
3076 first_visible_column = FromPixelToColumn (horiz_pixeloffset, out unused);
3078 col = FromPixelToColumn (max_pixel, out unused);
3080 visible_column_count = 1 + col - first_visible_column;
3082 visible_column_count = 0;
3083 for (int i = first_visible_column; i <= col; i ++) {
3084 if (CurrentTableStyle.GridColumnStyles[i].bound)
3085 visible_column_count++;
3088 if (first_visible_column + visible_column_count < CurrentTableStyle.GridColumnStyles.Count) {
3089 visible_column_count++; // Partially visible column
3093 void UpdateVisibleRowCount ()
3095 visible_row_count = GetVisibleRowCount (cells_area.Height);
3097 CalcRowHeaders (); // Height depends on num of visible rows
3100 void InvalidateCaption ()
3102 if (caption_area.IsEmpty)
3105 Invalidate (caption_area);
3108 void InvalidateRow (int row)
3110 if (row < FirstVisibleRow || row > FirstVisibleRow + VisibleRowCount)
3113 Rectangle rect_row = new Rectangle ();
3115 rect_row.X = cells_area.X;
3116 rect_row.Width = width_of_all_columns;
3117 if (rect_row.Width > cells_area.Width)
3118 rect_row.Width = cells_area.Width;
3119 rect_row.Height = rows[row].Height;
3120 rect_row.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3121 Invalidate (rect_row);
3124 void InvalidateRowHeader (int row)
3126 Rectangle rect_rowhdr = new Rectangle ();
3127 rect_rowhdr.X = row_headers_area.X;
3128 rect_rowhdr.Width = row_headers_area.Width;
3129 rect_rowhdr.Height = rows[row].Height;
3130 rect_rowhdr.Y = row_headers_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3131 Invalidate (rect_rowhdr);
3134 internal void InvalidateColumn (DataGridColumnStyle column)
3136 Rectangle rect_col = new Rectangle ();
3140 col = CurrentTableStyle.GridColumnStyles.IndexOf (column);
3145 rect_col.Width = column.Width;
3146 col_pixel = GetColumnStartingPixel (col);
3147 rect_col.X = cells_area.X + col_pixel - horiz_pixeloffset;
3148 rect_col.Y = cells_area.Y;
3149 rect_col.Height = cells_area.Height;
3150 Invalidate (rect_col);
3153 void DrawResizeLineVert (int x)
3155 XplatUI.DrawReversibleRectangle (Handle,
3156 new Rectangle (x, cells_area.Y, 1, cells_area.Height - 3),
3160 void DrawResizeLineHoriz (int y)
3162 XplatUI.DrawReversibleRectangle (Handle,
3163 new Rectangle (cells_area.X, y, cells_area.Width - 3, 1),
3167 void SetUpHorizontalScrollBar (out int maximum)
3169 maximum = width_of_all_columns;
3171 horiz_scrollbar.Location = new Point (ClientRectangle.X, ClientRectangle.Y +
3172 ClientRectangle.Height - horiz_scrollbar.Height);
3174 horiz_scrollbar.LargeChange = cells_area.Width;
3177 void SetUpVerticalScrollBar (out int height, out int maximum)
3181 y = ClientRectangle.Y + parent_rows.Y + parent_rows.Height;
3182 height = ClientRectangle.Height - parent_rows.Y - parent_rows.Height;
3184 vert_scrollbar.Location = new Point (ClientRectangle.X +
3185 ClientRectangle.Width - vert_scrollbar.Width, y);
3187 maximum = RowsCount;
3189 if (ShowEditRow && RowsCount > 0) {
3193 vert_scrollbar.LargeChange = VLargeChange;
3196 #endregion // Public Instance Methods
3198 #region Instance Properties
3199 // Returns the ColumnHeaders area excluding the rectangle shared with RowHeaders
3200 internal Rectangle ColumnHeadersArea {
3202 Rectangle columns_area = column_headers_area;
3204 if (CurrentTableStyle.CurrentRowHeadersVisible) {
3205 columns_area.X += RowHeaderWidth;
3206 columns_area.Width -= RowHeaderWidth;
3208 return columns_area;
3212 bool ShowingColumnHeaders {
3213 get { return ColumnHeadersVisible && CurrentTableStyle.GridColumnStyles.Count > 0; }
3216 internal Rectangle RowHeadersArea {
3217 get { return row_headers_area; }
3220 internal Rectangle ParentRowsArea {
3221 get { return parent_rows; }
3225 get { return VisibleRowCount; }
3228 #endregion Instance Properties
3230 #endregion // Code originally in DataGridDrawingLogic.cs