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 internal bool pending_new_row;
270 bool cursor_in_add_row;
271 bool add_row_changed;
272 internal bool is_editing; // Current cell is edit mode
275 internal Stack data_source_stack;
277 #endregion // Local Variables
279 #region Public Constructors
282 allow_navigation = true;
283 background_color = def_background_color;
284 border_style = BorderStyle.Fixed3D;
285 caption_backcolor = def_caption_backcolor;
286 caption_forecolor = def_caption_forecolor;
287 caption_text = string.Empty;
288 caption_visible = true;
289 datamember = string.Empty;
290 parent_rows_backcolor = def_parent_rows_backcolor;
291 parent_rows_forecolor = def_parent_rows_forecolor;
292 parent_rows_visible = true;
293 current_cell = new DataGridCell ();
294 parent_rows_label_style = DataGridParentRowsLabelStyle.Both;
295 selected_rows = new Hashtable ();
296 selection_start = -1;
297 rows = new DataGridRelationshipRow [0];
299 default_style = new DataGridTableStyle (true);
300 grid_style = new DataGridTableStyle ();
302 styles_collection = new GridTableStylesCollection (this);
303 styles_collection.CollectionChanged += new CollectionChangeEventHandler (OnTableStylesCollectionChanged);
305 CurrentTableStyle = grid_style;
307 horiz_scrollbar = new ImplicitHScrollBar ();
308 horiz_scrollbar.Scroll += new ScrollEventHandler (GridHScrolled);
309 vert_scrollbar = new ImplicitVScrollBar ();
310 vert_scrollbar.Scroll += new ScrollEventHandler (GridVScrolled);
312 SetStyle (ControlStyles.UserMouse, true);
314 data_source_stack = new Stack ();
316 back_button_image = ResourceImageLoader.Get ("go-previous.png");
317 back_button_image.MakeTransparent (Color.Transparent);
318 parent_rows_button_image = ResourceImageLoader.Get ("go-top.png");
319 parent_rows_button_image.MakeTransparent (Color.Transparent);
322 #endregion // Public Constructor
324 #region Public Instance Properties
327 public bool AllowNavigation {
328 get { return allow_navigation; }
330 if (allow_navigation != value) {
331 allow_navigation = value;
332 OnAllowNavigationChanged (EventArgs.Empty);
338 public bool AllowSorting {
339 get { return grid_style.AllowSorting; }
340 set { grid_style.AllowSorting = value; }
343 public Color AlternatingBackColor {
344 get { return grid_style.AlternatingBackColor; }
345 set { grid_style.AlternatingBackColor = value; }
348 public override Color BackColor {
349 get { return grid_style.BackColor; }
350 set { grid_style.BackColor = value; }
353 public Color BackgroundColor {
354 get { return background_color; }
356 if (background_color != value) {
357 background_color = value;
358 OnBackgroundColorChanged (EventArgs.Empty);
365 [EditorBrowsable(EditorBrowsableState.Never)]
366 public override Image BackgroundImage {
367 get { return base.BackgroundImage; }
369 if (base.BackgroundImage == value)
372 base.BackgroundImage = value;
379 [EditorBrowsable (EditorBrowsableState.Never)]
380 public override ImageLayout BackgroundImageLayout {
381 get { return base.BackgroundImageLayout; }
382 set { base.BackgroundImageLayout = value; }
387 [DefaultValue(BorderStyle.Fixed3D)]
388 public BorderStyle BorderStyle {
389 get { return InternalBorderStyle; }
391 InternalBorderStyle = value;
392 CalcAreasAndInvalidate ();
393 OnBorderStyleChanged (EventArgs.Empty);
397 public Color CaptionBackColor {
398 get { return caption_backcolor; }
400 if (caption_backcolor != value) {
401 caption_backcolor = value;
402 InvalidateCaption ();
409 public Font CaptionFont {
411 if (caption_font == null)
412 return new Font (Font, FontStyle.Bold);
417 if (caption_font != null && caption_font.Equals (value))
420 caption_font = value;
421 CalcAreasAndInvalidate ();
425 public Color CaptionForeColor {
426 get { return caption_forecolor; }
428 if (caption_forecolor != value) {
429 caption_forecolor = value;
430 InvalidateCaption ();
437 public string CaptionText {
438 get { return caption_text; }
440 if (caption_text != value) {
441 caption_text = value;
442 InvalidateCaption ();
448 public bool CaptionVisible {
449 get { return caption_visible; }
451 if (caption_visible != value) {
453 caption_visible = value;
454 CalcAreasAndInvalidate ();
455 OnCaptionVisibleChanged (EventArgs.Empty);
461 public bool ColumnHeadersVisible {
462 get { return grid_style.ColumnHeadersVisible; }
464 if (grid_style.ColumnHeadersVisible != value) {
465 grid_style.ColumnHeadersVisible = value;
468 // UIA Framework: To keep track of header
469 OnUIAColumnHeadersVisibleChanged ();
475 bool setting_current_cell;
478 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
479 public DataGridCell CurrentCell {
480 get { return current_cell; }
482 if (setting_current_cell)
484 setting_current_cell = true;
486 if (!IsHandleCreated) {
487 setting_current_cell = false;
488 throw new Exception ("CurrentCell cannot be set at this time.");
491 if (current_cell.Equals (value)) {
492 setting_current_cell = false;
496 /* make sure the new cell fits in the correct bounds for [row,column] */
497 if (ReadOnly && value.RowNumber > RowsCount - 1)
498 value.RowNumber = RowsCount - 1;
499 else if (value.RowNumber > RowsCount)
500 value.RowNumber = RowsCount;
501 if (value.ColumnNumber >= CurrentTableStyle.GridColumnStyles.Count)
502 value.ColumnNumber = CurrentTableStyle.GridColumnStyles.Count == 0 ? 0 : CurrentTableStyle.GridColumnStyles.Count - 1;
505 /* now make sure we don't go negative */
506 if (value.RowNumber < 0) value.RowNumber = 0;
507 if (value.ColumnNumber < 0) value.ColumnNumber = 0;
509 bool was_changing = is_changing;
511 add_row_changed = add_row_changed || was_changing;
514 if (value.RowNumber != current_cell.RowNumber) {
515 if (!from_positionchanged_handler) {
517 ListManager.EndCurrentEdit ();
519 catch (Exception e) {
520 DialogResult r = MessageBox.Show (String.Format ("{0} Do you wish to correct the value?", e.Message),
521 "Error when committing the row to the original data source",
522 MessageBoxButtons.YesNo);
523 if (r == DialogResult.Yes) {
524 InvalidateRowHeader (value.RowNumber);
525 InvalidateRowHeader (current_cell.RowNumber);
526 setting_current_cell = false;
531 ListManager.CancelCurrentEdit ();
535 if (value.RowNumber == RowsCount && !ListManager.AllowNew)
539 int old_row = current_cell.RowNumber;
541 current_cell = value;
543 EnsureCellVisibility (value);
545 if (CurrentRow == RowsCount && ListManager.AllowNew) {
546 cursor_in_add_row = true;
547 add_row_changed = false;
548 pending_new_row = true;
551 cursor_in_add_row = false;
552 pending_new_row = false;
555 InvalidateRowHeader (old_row);
556 InvalidateRowHeader (current_cell.RowNumber);
558 list_manager.Position = current_cell.RowNumber;
560 OnCurrentCellChanged (EventArgs.Empty);
562 if (!from_positionchanged_handler)
565 setting_current_cell = false;
570 get { return current_cell.RowNumber; }
571 set { CurrentCell = new DataGridCell (value, current_cell.ColumnNumber); }
575 get { return current_cell.ColumnNumber; }
576 set { CurrentCell = new DataGridCell (current_cell.RowNumber, value); }
580 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
581 public int CurrentRowIndex {
583 if (ListManager == null)
588 set { CurrentRow = value; }
592 [EditorBrowsable(EditorBrowsableState.Never)]
593 public override Cursor Cursor {
594 get { return base.Cursor; }
595 set { base.Cursor = value; }
599 [Editor ("System.Windows.Forms.Design.DataMemberListEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
600 public string DataMember {
601 get { return datamember; }
603 if (BindingContext != null) {
604 SetDataSource (datasource, value);
607 if (list_manager != null)
610 refetch_list_manager = true;
616 [RefreshProperties(RefreshProperties.Repaint)]
618 [AttributeProvider (typeof (IListSource))]
620 [TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " + Consts.AssemblySystem_Design)]
622 public object DataSource {
623 get { return datasource; }
625 if (BindingContext != null) {
626 SetDataSource (value, ListManager == null ? datamember : string.Empty);
630 if (list_manager != null)
631 datamember = string.Empty;
633 if (list_manager != null)
635 refetch_list_manager = true;
640 protected override Size DefaultSize {
641 get { return new Size (130, 80); }
645 public int FirstVisibleColumn {
646 get { return first_visible_column; }
649 [DefaultValue(false)]
650 public bool FlatMode {
651 get { return flatmode; }
653 if (flatmode != value) {
655 OnFlatModeChanged (EventArgs.Empty);
661 public override Color ForeColor {
662 get { return grid_style.ForeColor; }
663 set { grid_style.ForeColor = value; }
666 public Color GridLineColor {
667 get { return grid_style.GridLineColor; }
669 if (value == Color.Empty)
670 throw new ArgumentException ("Color.Empty value is invalid.");
672 grid_style.GridLineColor = value;
676 [DefaultValue(DataGridLineStyle.Solid)]
677 public DataGridLineStyle GridLineStyle {
678 get { return grid_style.GridLineStyle; }
679 set { grid_style.GridLineStyle = value; }
682 public Color HeaderBackColor {
683 get { return grid_style.HeaderBackColor; }
685 if (value == Color.Empty)
686 throw new ArgumentException ("Color.Empty value is invalid.");
688 grid_style.HeaderBackColor = value;
692 public Font HeaderFont {
693 get { return grid_style.HeaderFont; }
694 set { grid_style.HeaderFont = value; }
697 public Color HeaderForeColor {
698 get { return grid_style.HeaderForeColor; }
699 set { grid_style.HeaderForeColor = value; }
702 protected ScrollBar HorizScrollBar {
703 get { return horiz_scrollbar; }
705 internal ScrollBar HScrollBar {
706 get { return horiz_scrollbar; }
709 internal int HorizPixelOffset {
710 get { return horiz_pixeloffset; }
713 internal bool IsChanging {
714 get { return is_changing; }
717 public object this [DataGridCell cell] {
718 get { return this [cell.RowNumber, cell.ColumnNumber]; }
719 set { this [cell.RowNumber, cell.ColumnNumber] = value; }
722 public object this [int rowIndex, int columnIndex] {
723 get { return CurrentTableStyle.GridColumnStyles[columnIndex].GetColumnValueAtRow (ListManager,
726 CurrentTableStyle.GridColumnStyles[columnIndex].SetColumnValueAtRow (ListManager,
730 // UIA Framework: Raising changes in datasource.
731 OnUIAGridCellChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh,
732 new DataGridCell (rowIndex,
738 public Color LinkColor {
739 get { return grid_style.LinkColor; }
740 set { grid_style.LinkColor = value; }
743 internal Font LinkFont {
744 get { return new Font (Font, FontStyle.Underline); }
751 [EditorBrowsable(EditorBrowsableState.Never)]
752 public Color LinkHoverColor {
753 get { return grid_style.LinkHoverColor; }
754 set { grid_style.LinkHoverColor = value; }
758 [EditorBrowsable(EditorBrowsableState.Advanced)]
759 protected internal CurrencyManager ListManager {
761 if (list_manager == null && refetch_list_manager) {
762 SetDataSource (datasource, datamember);
763 refetch_list_manager = false;
768 set { throw new NotSupportedException ("Operation is not supported."); }
771 public Color ParentRowsBackColor {
772 get { return parent_rows_backcolor; }
774 if (parent_rows_backcolor != value) {
775 parent_rows_backcolor = value;
776 if (parent_rows_visible) {
783 public Color ParentRowsForeColor {
784 get { return parent_rows_forecolor; }
786 if (parent_rows_forecolor != value) {
787 parent_rows_forecolor = value;
788 if (parent_rows_visible) {
795 [DefaultValue(DataGridParentRowsLabelStyle.Both)]
796 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
797 public DataGridParentRowsLabelStyle ParentRowsLabelStyle {
798 get { return parent_rows_label_style; }
800 if (parent_rows_label_style != value) {
801 parent_rows_label_style = value;
802 if (parent_rows_visible) {
806 OnParentRowsLabelStyleChanged (EventArgs.Empty);
812 public bool ParentRowsVisible {
813 get { return parent_rows_visible; }
815 if (parent_rows_visible != value) {
816 parent_rows_visible = value;
817 CalcAreasAndInvalidate ();
818 OnParentRowsVisibleChanged (EventArgs.Empty);
823 // Settting this property seems to have no effect.
825 [TypeConverter(typeof(DataGridPreferredColumnWidthTypeConverter))]
826 public int PreferredColumnWidth {
827 get { return grid_style.PreferredColumnWidth; }
828 set { grid_style.PreferredColumnWidth = value; }
831 public int PreferredRowHeight {
832 get { return grid_style.PreferredRowHeight; }
833 set { grid_style.PreferredRowHeight = value; }
836 [DefaultValue(false)]
837 public bool ReadOnly {
838 get { return _readonly; }
840 if (_readonly != value) {
842 OnReadOnlyChanged (EventArgs.Empty);
843 CalcAreasAndInvalidate ();
849 public bool RowHeadersVisible {
850 get { return grid_style.RowHeadersVisible; }
851 set { grid_style.RowHeadersVisible = value; }
855 public int RowHeaderWidth {
856 get { return grid_style.RowHeaderWidth; }
857 set { grid_style.RowHeaderWidth = value; }
860 internal DataGridRelationshipRow[] DataGridRows {
865 public Color SelectionBackColor {
866 get { return grid_style.SelectionBackColor; }
867 set { grid_style.SelectionBackColor = value; }
870 public Color SelectionForeColor {
871 get { return grid_style.SelectionForeColor; }
872 set { grid_style.SelectionForeColor = value; }
875 public override ISite Site {
876 get { return base.Site; }
877 set { base.Site = value; }
881 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
882 public GridTableStylesCollection TableStyles {
883 get { return styles_collection; }
888 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
889 [EditorBrowsable(EditorBrowsableState.Never)]
890 public override string Text {
891 get { return base.Text; }
892 set { base.Text = value; }
896 [EditorBrowsable(EditorBrowsableState.Advanced)]
897 protected ScrollBar VertScrollBar {
898 get { return vert_scrollbar; }
900 internal ScrollBar VScrollBar {
901 get { return vert_scrollbar; }
905 public int VisibleColumnCount {
906 get { return visible_column_count; }
910 public int VisibleRowCount {
911 get { return visible_row_count; }
914 #endregion // Public Instance Properties
916 #region Private Instance Properties
917 internal DataGridTableStyle CurrentTableStyle {
918 get { return current_style; }
920 if (current_style != value) {
921 if (current_style != null)
922 DisconnectTableStyleEvents ();
924 current_style = value;
926 if (current_style != null) {
927 current_style.DataGrid = this;
928 ConnectTableStyleEvents ();
930 CalcAreasAndInvalidate ();
935 internal int FirstVisibleRow {
936 get { return first_visible_row; }
939 internal int RowsCount {
940 get { return ListManager != null ? ListManager.Count : 0; }
943 internal int RowHeight {
945 if (CurrentTableStyle.CurrentPreferredRowHeight > Font.Height + 3 + 1 /* line */)
946 return CurrentTableStyle.CurrentPreferredRowHeight;
948 return Font.Height + 3 + 1 /* line */;
952 internal override bool ScaleChildrenInternal {
953 get { return false; }
956 internal bool ShowEditRow {
958 if (ListManager != null && !ListManager.AllowNew)
965 internal bool ShowParentRows {
966 get { return ParentRowsVisible && data_source_stack.Count > 0; }
969 #endregion Private Instance Properties
971 #region Public Instance Methods
976 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
978 InvalidateRowHeader (current_cell.RowNumber);
982 public bool BeginEdit (DataGridColumnStyle gridColumn, int rowNumber)
987 int column = CurrentTableStyle.GridColumnStyles.IndexOf (gridColumn);
991 CurrentCell = new DataGridCell (rowNumber, column);
993 /* force editing of CurrentCell if we aren't already editing */
999 public void BeginInit ()
1003 protected virtual void CancelEditing ()
1005 if (CurrentTableStyle.GridColumnStyles.Count == 0)
1008 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].ConcedeFocus ();
1011 if (current_cell.ColumnNumber < CurrentTableStyle.GridColumnStyles.Count)
1012 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
1013 InvalidateRowHeader (current_cell.RowNumber);
1016 if (cursor_in_add_row && !is_changing) {
1017 ListManager.CancelCurrentEdit ();
1020 is_changing = false;
1024 public void Collapse (int row)
1026 if (!rows[row].IsExpanded)
1030 rows[row].IsExpanded = false;
1031 for (int i = 1; i < rows.Length - row; i ++)
1032 rows[row + i].VerticalOffset -= rows[row].RelationHeight;
1034 rows[row].height -= rows[row].RelationHeight;
1035 rows[row].RelationHeight = 0;
1036 ResumeLayout (false);
1038 /* XX need to redraw from @row down */
1039 CalcAreasAndInvalidate ();
1042 protected internal virtual void ColumnStartedEditing (Control editingControl)
1044 ColumnStartedEditing (editingControl.Bounds);
1047 protected internal virtual void ColumnStartedEditing (Rectangle bounds)
1049 bool need_invalidate = is_changing == false;
1050 // XXX calculate the row header to invalidate
1051 // instead of using CurrentRow
1054 if (cursor_in_add_row && need_invalidate)
1055 RecreateDataGridRows (true);
1057 if (need_invalidate)
1058 InvalidateRowHeader (CurrentRow);
1061 protected override AccessibleObject CreateAccessibilityInstance ()
1063 return base.CreateAccessibilityInstance ();
1066 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop)
1068 return CreateGridColumn (prop, false);
1071 [MonoTODO ("Not implemented, will throw NotImplementedException")]
1072 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop, bool isDefault)
1074 throw new NotImplementedException();
1077 protected override void Dispose (bool disposing)
1079 base.Dispose (disposing);
1082 public bool EndEdit (DataGridColumnStyle gridColumn, int rowNumber, bool shouldAbort)
1084 if (shouldAbort || (_readonly || gridColumn.TableStyleReadOnly || gridColumn.ReadOnly))
1085 gridColumn.Abort (rowNumber);
1087 gridColumn.Commit (ListManager, rowNumber);
1088 gridColumn.ConcedeFocus ();
1091 if (is_editing || is_changing) {
1093 is_changing = false;
1094 InvalidateRowHeader (rowNumber);
1099 public void EndInit ()
1101 if (grid_style != null)
1102 grid_style.DataGrid = this;
1105 public void Expand (int row)
1107 if (rows[row].IsExpanded)
1110 rows[row].IsExpanded = true;
1114 string[] relations = CurrentTableStyle.Relations;
1115 StringBuilder relation_builder = new StringBuilder ("");
1117 for (i = 0; i < relations.Length; i ++) {
1119 relation_builder.Append ("\n");
1121 relation_builder.Append (relations[i]);
1123 string relation_text = relation_builder.ToString ();
1125 SizeF measured_area = TextRenderer.MeasureString (relation_text, LinkFont);
1127 rows[row].relation_area = new Rectangle (cells_area.X + 1,
1128 0, /* updated as needed at the usage sites for relation_area */
1129 (int)measured_area.Width + 4,
1130 Font.Height * relations.Length);
1132 for (i = 1; i < rows.Length - row; i ++)
1133 rows[row + i].VerticalOffset += rows[row].relation_area.Height;
1134 rows[row].height += rows[row].relation_area.Height;
1135 rows[row].RelationHeight = rows[row].relation_area.Height;
1137 /* XX need to redraw from @row down */
1138 CalcAreasAndInvalidate ();
1141 public Rectangle GetCellBounds (DataGridCell dgc)
1143 return GetCellBounds (dgc.RowNumber, dgc.ColumnNumber);
1146 public Rectangle GetCellBounds (int row, int col)
1148 Rectangle bounds = new Rectangle ();
1151 bounds.Width = CurrentTableStyle.GridColumnStyles[col].Width;
1152 bounds.Height = rows[row].Height - rows[row].RelationHeight;
1153 bounds.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1154 col_pixel = GetColumnStartingPixel (col);
1155 bounds.X = cells_area.X + col_pixel - horiz_pixeloffset;
1159 public Rectangle GetCurrentCellBounds ()
1161 return GetCellBounds (current_cell.RowNumber, current_cell.ColumnNumber);
1164 protected virtual string GetOutputTextDelimiter ()
1166 return string.Empty;
1169 protected virtual void GridHScrolled (object sender, ScrollEventArgs se)
1171 if (se.NewValue == horiz_pixeloffset ||
1172 se.Type == ScrollEventType.EndScroll) {
1176 ScrollToColumnInPixels (se.NewValue);
1179 protected virtual void GridVScrolled (object sender, ScrollEventArgs se)
1181 int old_first_visible_row = first_visible_row;
1182 first_visible_row = se.NewValue;
1184 if (first_visible_row == old_first_visible_row)
1187 UpdateVisibleRowCount ();
1189 if (first_visible_row == old_first_visible_row)
1192 ScrollToRow (old_first_visible_row, first_visible_row);
1195 public HitTestInfo HitTest (Point position)
1197 return HitTest (position.X, position.Y);
1200 const int RESIZE_HANDLE_HORIZ_SIZE = 5;
1201 const int RESIZE_HANDLE_VERT_SIZE = 3;
1203 // From Point to Cell
1204 public HitTestInfo HitTest (int x, int y)
1206 if (column_headers_area.Contains (x, y)) {
1207 int offset_x = x + horiz_pixeloffset;
1209 int column_under_mouse = FromPixelToColumn (offset_x, out column_x);
1211 if (column_under_mouse == -1)
1212 return new HitTestInfo (-1, -1, HitTestType.None);
1214 if ((column_x + CurrentTableStyle.GridColumnStyles[column_under_mouse].Width - offset_x < RESIZE_HANDLE_HORIZ_SIZE)
1215 && column_under_mouse < CurrentTableStyle.GridColumnStyles.Count) {
1217 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnResize);
1220 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnHeader);
1224 if (row_headers_area.Contains (x, y)) {
1226 int rcnt = FirstVisibleRow + VisibleRowCount;
1227 for (int r = FirstVisibleRow; r < rcnt; r++) {
1228 posy = cells_area.Y + rows[r].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1229 if (y <= posy + rows[r].Height) {
1230 if ((posy + rows[r].Height) - y < RESIZE_HANDLE_VERT_SIZE) {
1231 return new HitTestInfo (r, -1, HitTestType.RowResize);
1234 return new HitTestInfo (r, -1, HitTestType.RowHeader);
1240 if (caption_area.Contains (x, y)) {
1241 return new HitTestInfo (-1, -1, HitTestType.Caption);
1244 if (parent_rows.Contains (x, y)) {
1245 return new HitTestInfo (-1, -1, HitTestType.ParentRows);
1248 int pos_y, pos_x, width;
1249 int rowcnt = FirstVisibleRow + VisibleRowCount;
1250 for (int row = FirstVisibleRow; row < rowcnt; row++) {
1252 pos_y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1253 if (y <= pos_y + rows[row].Height) {
1255 int column_cnt = first_visible_column + visible_column_count;
1256 if (column_cnt > 0) {
1257 for (int column = first_visible_column; column < column_cnt; column++) {
1258 if (CurrentTableStyle.GridColumnStyles[column].bound == false)
1260 col_pixel = GetColumnStartingPixel (column);
1261 pos_x = cells_area.X + col_pixel - horiz_pixeloffset;
1262 width = CurrentTableStyle.GridColumnStyles[column].Width;
1264 if (x <= pos_x + width) { // Column found
1265 return new HitTestInfo (row, column, HitTestType.Cell);
1269 else if (CurrentTableStyle.HasRelations) {
1270 /* XXX this needs checking against MS somehow... */
1271 if (x < rows[row].relation_area.X + rows[row].relation_area.Width)
1272 return new HitTestInfo (row, 0/*XXX?*/, HitTestType.Cell);
1279 return new HitTestInfo ();
1282 public bool IsExpanded (int rowNumber)
1284 return (rows[rowNumber].IsExpanded);
1287 public bool IsSelected (int row)
1289 return rows[row].IsSelected;
1292 public void NavigateBack ()
1294 if (data_source_stack.Count == 0)
1297 DataGridDataSource source = (DataGridDataSource)data_source_stack.Pop ();
1298 list_manager = source.list_manager;
1300 selected_rows = source.SelectedRows;
1301 selection_start = source.SelectionStart;
1302 SetDataSource (source.data_source, source.data_member);
1304 CurrentCell = source.current;
1307 public void NavigateTo (int rowNumber, string relationName)
1309 if (allow_navigation == false)
1312 DataGridDataSource previous_source = new DataGridDataSource (this, list_manager, datasource, datamember, list_manager.Current, CurrentCell);
1313 previous_source.Rows = rows;
1314 previous_source.SelectedRows = selected_rows;
1315 previous_source.SelectionStart = selection_start;
1317 data_source_stack.Push (previous_source);
1320 selected_rows = new Hashtable ();
1321 selection_start = -1;
1323 DataMember = String.Format ("{0}.{1}", DataMember, relationName);
1324 OnDataSourceChanged (EventArgs.Empty);
1327 protected virtual void OnAllowNavigationChanged (EventArgs e)
1329 EventHandler eh = (EventHandler)(Events [AllowNavigationChangedEvent]);
1334 protected void OnBackButtonClicked (object sender, EventArgs e)
1336 EventHandler eh = (EventHandler)(Events [BackButtonClickEvent]);
1341 protected override void OnBackColorChanged (EventArgs e)
1343 base.OnBackColorChanged (e);
1346 protected virtual void OnBackgroundColorChanged (EventArgs e)
1348 EventHandler eh = (EventHandler)(Events [BackgroundColorChangedEvent]);
1353 protected override void OnBindingContextChanged (EventArgs e)
1355 base.OnBindingContextChanged (e);
1357 SetDataSource (datasource, datamember);
1360 protected virtual void OnBorderStyleChanged (EventArgs e)
1362 EventHandler eh = (EventHandler)(Events [BorderStyleChangedEvent]);
1367 protected virtual void OnCaptionVisibleChanged (EventArgs e)
1369 EventHandler eh = (EventHandler)(Events [CaptionVisibleChangedEvent]);
1374 protected virtual void OnCurrentCellChanged (EventArgs e)
1376 EventHandler eh = (EventHandler)(Events [CurrentCellChangedEvent]);
1381 protected virtual void OnDataSourceChanged (EventArgs e)
1383 EventHandler eh = (EventHandler)(Events [DataSourceChangedEvent]);
1388 protected override void OnEnter (EventArgs e)
1394 protected virtual void OnFlatModeChanged (EventArgs e)
1396 EventHandler eh = (EventHandler)(Events [FlatModeChangedEvent]);
1401 protected override void OnFontChanged (EventArgs e)
1404 base.OnFontChanged (e);
1407 protected override void OnForeColorChanged (EventArgs e)
1409 base.OnForeColorChanged (e);
1412 protected override void OnHandleCreated (EventArgs e)
1414 base.OnHandleCreated (e);
1415 SetDataSource (datasource, datamember);
1418 protected override void OnHandleDestroyed (EventArgs e)
1420 base.OnHandleDestroyed (e);
1423 // It seems we have repeated code with ProcessKeyPreview, specifically
1424 // the call to ProcessGridKey. In practice it seems this event is *never* fired
1425 // since the key events are handled by the current column's textbox.
1426 // We are keeping commented anyway, in case we need to actually call it.
1427 protected override void OnKeyDown (KeyEventArgs ke)
1429 base.OnKeyDown (ke);
1431 /*if (ProcessGridKey (ke) == true)
1434 // TODO: we probably don't need this check,
1435 // since current_cell wouldn't have been set
1436 // to something invalid
1437 if (CurrentTableStyle.GridColumnStyles.Count > 0) {
1438 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].OnKeyDown
1439 (ke, current_cell.RowNumber, current_cell.ColumnNumber);
1443 protected override void OnKeyPress (KeyPressEventArgs kpe)
1445 base.OnKeyPress (kpe);
1448 protected override void OnLayout (LayoutEventArgs levent)
1450 base.OnLayout (levent);
1451 CalcAreasAndInvalidate ();
1454 protected override void OnLeave (EventArgs e)
1459 if (cursor_in_add_row) {
1460 ListManager.CancelCurrentEdit ();
1464 protected override void OnMouseDown (MouseEventArgs e)
1466 base.OnMouseDown (e);
1468 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1469 bool shift_pressed = ((Control.ModifierKeys & Keys.Shift) != 0);
1471 HitTestInfo testinfo;
1472 testinfo = HitTest (e.X, e.Y);
1474 switch (testinfo.Type) {
1475 case HitTestType.Cell:
1476 if (testinfo.Row < 0 || testinfo.Column < 0)
1479 if (rows[testinfo.Row].IsExpanded) {
1480 Rectangle relation_area = rows[testinfo.Row].relation_area;
1481 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1482 if (relation_area.Contains (e.X, e.Y)) {
1483 /* the click happened in the relation area, navigate to the new table */
1484 int relative = e.Y - relation_area.Y;
1485 NavigateTo (testinfo.Row, CurrentTableStyle.Relations[relative / LinkFont.Height]);
1490 DataGridCell new_cell = new DataGridCell (testinfo.Row, testinfo.Column);
1492 if ((new_cell.Equals (current_cell) == false) || (!is_editing)) {
1494 CurrentCell = new_cell;
1497 CurrentTableStyle.GridColumnStyles[testinfo.Column].OnMouseDown (e, testinfo.Row, testinfo.Column);
1502 case HitTestType.RowHeader:
1503 bool expansion_click = false;
1504 if (CurrentTableStyle.HasRelations) {
1505 if (e.X > row_headers_area.X + row_headers_area.Width / 2) {
1506 /* it's in the +/- space */
1507 if (IsExpanded (testinfo.Row))
1508 Collapse (testinfo.Row);
1510 Expand (testinfo.Row);
1512 expansion_click = true;
1517 CurrentRow = testinfo.Row;
1519 if (!ctrl_pressed && !shift_pressed && !expansion_click) {
1520 ResetSelection (); // Invalidates selected rows
1523 if ((shift_pressed || expansion_click) && selection_start != -1) {
1524 ShiftSelection (testinfo.Row);
1525 } else { // ctrl_pressed or single item
1526 selection_start = testinfo.Row;
1527 Select (testinfo.Row);
1530 OnRowHeaderClick (EventArgs.Empty);
1534 case HitTestType.ColumnHeader:
1535 if (CurrentTableStyle.GridColumnStyles.Count == 0)
1538 if (AllowSorting == false)
1541 if (ListManager.List is IBindingList == false)
1544 // Don't do any sort if we are empty, as .net does
1545 if (ListManager.Count == 0)
1548 ListSortDirection direction = ListSortDirection.Ascending;
1549 PropertyDescriptor prop = CurrentTableStyle.GridColumnStyles[testinfo.Column].PropertyDescriptor;
1550 IBindingList list = (IBindingList) ListManager.List;
1552 if (list.SortProperty != null) {
1553 CurrentTableStyle.GridColumnStyles[list.SortProperty].ArrowDrawingMode
1554 = DataGridColumnStyle.ArrowDrawing.No;
1557 if (prop == list.SortProperty && list.SortDirection == ListSortDirection.Ascending) {
1558 direction = ListSortDirection.Descending;
1561 CurrentTableStyle.GridColumnStyles[testinfo.Column].ArrowDrawingMode =
1562 direction == ListSortDirection.Ascending ?
1563 DataGridColumnStyle.ArrowDrawing.Ascending : DataGridColumnStyle.ArrowDrawing.Descending;
1565 list.ApplySort (prop, direction);
1567 if (this.is_editing)
1568 //CurrentTableStyle.GridColumnStyles[CurrentColumn].UpdateUI ();
1569 this.InvalidateColumn (CurrentTableStyle.GridColumnStyles[CurrentColumn]);
1573 case HitTestType.ColumnResize:
1574 if (e.Clicks == 2) {
1576 ColumnResize (testinfo.Column);
1578 resize_column = testinfo.Column;
1579 column_resize_active = true;
1580 resize_column_x = e.X;
1581 resize_column_width_delta = 0;
1583 DrawResizeLineVert (resize_column_x);
1587 case HitTestType.RowResize:
1588 if (e.Clicks == 2) {
1590 RowResize (testinfo.Row);
1592 resize_row = testinfo.Row;
1593 row_resize_active = true;
1595 resize_row_height_delta = 0;
1597 DrawResizeLineHoriz (resize_row_y);
1601 case HitTestType.Caption:
1602 if (back_button_rect.Contains (e.X, e.Y)) {
1603 back_button_active = true;
1604 Invalidate (back_button_rect);
1606 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1607 parent_rows_button_active = true;
1608 Invalidate (parent_rows_button_rect);
1617 protected override void OnMouseLeave (EventArgs e)
1619 base.OnMouseLeave (e);
1622 protected override void OnMouseMove (MouseEventArgs e)
1624 base.OnMouseMove (e);
1626 if (column_resize_active) {
1627 /* erase the old line */
1628 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1630 resize_column_width_delta = e.X - resize_column_x;
1632 /* draw the new line */
1633 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1636 else if (row_resize_active) {
1637 /* erase the old line */
1638 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1640 resize_row_height_delta = e.Y - resize_row_y;
1642 /* draw the new line */
1643 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1647 /* determine the cursor to use */
1648 HitTestInfo testinfo;
1649 testinfo = HitTest (e.X, e.Y);
1651 switch (testinfo.Type) {
1652 case HitTestType.ColumnResize:
1653 Cursor = Cursors.VSplit;
1655 case HitTestType.RowResize:
1656 Cursor = Cursors.HSplit;
1658 case HitTestType.Caption:
1659 Cursor = Cursors.Default;
1660 if (back_button_rect.Contains (e.X, e.Y)) {
1661 if (!back_button_mouseover)
1662 Invalidate (back_button_rect);
1663 back_button_mouseover = true;
1664 } else if (back_button_mouseover) {
1665 Invalidate (back_button_rect);
1666 back_button_mouseover = false;
1669 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1670 if (parent_rows_button_mouseover)
1671 Invalidate (parent_rows_button_rect);
1672 parent_rows_button_mouseover = true;
1673 } else if (parent_rows_button_mouseover) {
1674 Invalidate (parent_rows_button_rect);
1675 parent_rows_button_mouseover = false;
1678 case HitTestType.Cell:
1679 if (rows[testinfo.Row].IsExpanded) {
1680 Rectangle relation_area = rows[testinfo.Row].relation_area;
1681 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1682 if (relation_area.Contains (e.X, e.Y)) {
1683 Cursor = Cursors.Hand;
1688 Cursor = Cursors.Default;
1690 case HitTestType.RowHeader:
1691 if (e.Button == MouseButtons.Left)
1692 ShiftSelection (testinfo.Row);
1694 Cursor = Cursors.Default;
1697 Cursor = Cursors.Default;
1703 protected override void OnMouseUp (MouseEventArgs e)
1707 if (column_resize_active) {
1708 column_resize_active = false;
1709 if (resize_column_width_delta + CurrentTableStyle.GridColumnStyles[resize_column].Width < 0)
1710 resize_column_width_delta = -CurrentTableStyle.GridColumnStyles[resize_column].Width;
1711 CurrentTableStyle.GridColumnStyles[resize_column].Width += resize_column_width_delta;
1712 width_of_all_columns += resize_column_width_delta;
1715 } else if (row_resize_active) {
1716 row_resize_active = false;
1718 if (resize_row_height_delta + rows[resize_row].Height < 0)
1719 resize_row_height_delta = -rows[resize_row].Height;
1721 rows[resize_row].height = rows[resize_row].Height + resize_row_height_delta;
1722 for (int i = resize_row + 1; i < rows.Length; i ++)
1723 rows[i].VerticalOffset += resize_row_height_delta;
1726 CalcAreasAndInvalidate ();
1727 } else if (back_button_active) {
1728 if (back_button_rect.Contains (e.X, e.Y)) {
1729 Invalidate (back_button_rect);
1731 OnBackButtonClicked (this, EventArgs.Empty);
1733 back_button_active = false;
1734 } else if (parent_rows_button_active) {
1735 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1736 Invalidate (parent_rows_button_rect);
1737 ParentRowsVisible = !ParentRowsVisible;
1738 OnShowParentDetailsButtonClicked (this, EventArgs.Empty);
1740 parent_rows_button_active = false;
1744 protected override void OnMouseWheel (MouseEventArgs e)
1746 base.OnMouseWheel (e);
1748 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1751 if (ctrl_pressed) { // scroll horizontally
1752 if (!horiz_scrollbar.Visible)
1757 pixels = Math.Max (horiz_scrollbar.Minimum,
1758 horiz_scrollbar.Value - horiz_scrollbar.LargeChange);
1761 pixels = Math.Min (horiz_scrollbar.Maximum - horiz_scrollbar.LargeChange + 1,
1762 horiz_scrollbar.Value + horiz_scrollbar.LargeChange);
1765 GridHScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1766 horiz_scrollbar.Value = pixels;
1768 if (!vert_scrollbar.Visible)
1773 pixels = Math.Max (vert_scrollbar.Minimum,
1774 vert_scrollbar.Value - vert_scrollbar.LargeChange);
1777 pixels = Math.Min (vert_scrollbar.Maximum - vert_scrollbar.LargeChange + 1,
1778 vert_scrollbar.Value + vert_scrollbar.LargeChange);
1781 GridVScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1782 vert_scrollbar.Value = pixels;
1786 protected void OnNavigate (NavigateEventArgs e)
1788 EventHandler eh = (EventHandler)(Events [NavigateEvent]);
1793 protected override void OnPaint (PaintEventArgs pe)
1795 ThemeEngine.Current.DataGridPaint (pe, this);
1798 protected override void OnPaintBackground (PaintEventArgs ebe)
1802 protected virtual void OnParentRowsLabelStyleChanged (EventArgs e)
1804 EventHandler eh = (EventHandler)(Events [ParentRowsLabelStyleChangedEvent]);
1809 protected virtual void OnParentRowsVisibleChanged (EventArgs e)
1811 EventHandler eh = (EventHandler)(Events [ParentRowsVisibleChangedEvent]);
1816 protected virtual void OnReadOnlyChanged (EventArgs e)
1818 EventHandler eh = (EventHandler)(Events [ReadOnlyChangedEvent]);
1823 protected override void OnResize (EventArgs e)
1828 protected void OnRowHeaderClick (EventArgs e)
1830 EventHandler eh = (EventHandler)(Events [RowHeaderClickEvent]);
1835 protected void OnScroll (EventArgs e)
1837 EventHandler eh = (EventHandler)(Events [ScrollEvent]);
1842 protected void OnShowParentDetailsButtonClicked (object sender, EventArgs e)
1844 EventHandler eh = (EventHandler)(Events [ShowParentDetailsButtonClickEvent]);
1849 protected override bool ProcessDialogKey (Keys keyData)
1851 return ProcessGridKey (new KeyEventArgs (keyData));
1854 void UpdateSelectionAfterCursorMove (bool extend_selection)
1856 if (extend_selection) {
1858 ShiftSelection (CurrentRow);
1861 selection_start = CurrentRow;
1865 protected bool ProcessGridKey (KeyEventArgs ke)
1867 bool ctrl_pressed = ((ke.Modifiers & Keys.Control) != 0);
1868 //bool alt_pressed = ((ke.Modifiers & Keys.Alt) != 0);
1869 bool shift_pressed = ((ke.Modifiers & Keys.Shift) != 0);
1871 switch (ke.KeyCode) {
1878 if (cursor_in_add_row && CurrentRow > 0)
1888 CurrentTableStyle.GridColumnStyles[CurrentColumn].EnterNullValue ();
1899 if (shift_pressed) {
1900 if (CurrentColumn > 0)
1902 else if ((CurrentRow > 0) && (CurrentColumn == 0))
1903 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1905 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1)
1907 else if ((CurrentRow <= RowsCount) && (CurrentColumn == CurrentTableStyle.GridColumnStyles.Count - 1))
1908 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1911 UpdateSelectionAfterCursorMove (false);
1917 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1919 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1) {
1921 } else if (CurrentRow < RowsCount - 1
1922 || (CurrentRow == RowsCount - 1
1923 && !cursor_in_add_row)) {
1924 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1928 UpdateSelectionAfterCursorMove (false);
1936 if (current_cell.ColumnNumber > 0)
1938 else if (CurrentRow > 0)
1939 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1942 UpdateSelectionAfterCursorMove (false);
1949 else if (CurrentRow > 0)
1952 UpdateSelectionAfterCursorMove (shift_pressed);
1958 CurrentRow = RowsCount - 1;
1959 else if (CurrentRow < RowsCount - 1)
1961 else if (CurrentRow == RowsCount - 1 && cursor_in_add_row && (add_row_changed || is_changing))
1963 else if (CurrentRow == RowsCount - 1 && !cursor_in_add_row && !shift_pressed)
1966 UpdateSelectionAfterCursorMove (shift_pressed);
1971 if (CurrentRow > VLargeChange)
1972 CurrentRow -= VLargeChange;
1976 UpdateSelectionAfterCursorMove (shift_pressed);
1981 if (CurrentRow < RowsCount - VLargeChange)
1982 CurrentRow += VLargeChange;
1984 CurrentRow = RowsCount - 1;
1986 UpdateSelectionAfterCursorMove (shift_pressed);
1992 CurrentCell = new DataGridCell (0, 0);
1996 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
2002 CurrentCell = new DataGridCell (RowsCount - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
2004 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
2006 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
2013 else if (selected_rows.Keys.Count > 0) {
2014 foreach (int row in selected_rows.Keys)
2015 ListManager.RemoveAt (row);
2016 selected_rows.Clear ();
2017 CalcAreasAndInvalidate ();
2023 return false; // message not processed
2026 protected override bool ProcessKeyPreview (ref Message m)
2028 if ((Msg) m.Msg == Msg.WM_KEYDOWN) {
2029 Keys key = (Keys) m.WParam.ToInt32 ();
2030 KeyEventArgs ke = new KeyEventArgs (key);
2031 if (ProcessGridKey (ke))
2034 // if we receive a key event, make sure that input is actually
2035 // taken into account.
2038 InvalidateRow (current_cell.RowNumber);
2043 return base.ProcessKeyPreview (ref m);
2046 protected bool ProcessTabKey (Keys keyData)
2051 public void ResetAlternatingBackColor ()
2053 grid_style.AlternatingBackColor = default_style.AlternatingBackColor;
2056 public override void ResetBackColor ()
2058 grid_style.BackColor = default_style.BackColor;
2061 public override void ResetForeColor ()
2063 grid_style.ForeColor = default_style.ForeColor;
2066 public void ResetGridLineColor ()
2068 grid_style.GridLineColor = default_style.GridLineColor;
2071 public void ResetHeaderBackColor ()
2073 grid_style.HeaderBackColor = default_style.HeaderBackColor;
2076 public void ResetHeaderFont ()
2078 grid_style.HeaderFont = null;
2081 public void ResetHeaderForeColor ()
2083 grid_style.HeaderForeColor = default_style.HeaderForeColor;
2086 public void ResetLinkColor ()
2088 grid_style.LinkColor = default_style.LinkColor;
2091 public void ResetLinkHoverColor ()
2093 grid_style.LinkHoverColor = default_style.LinkHoverColor;
2096 protected void ResetSelection ()
2098 InvalidateSelection ();
2099 selected_rows.Clear ();
2100 selection_start = -1;
2103 void InvalidateSelection ()
2105 foreach (int row in selected_rows.Keys) {
2106 rows[row].IsSelected = false;
2107 InvalidateRow (row);
2111 public void ResetSelectionBackColor ()
2113 grid_style.SelectionBackColor = default_style.SelectionBackColor;
2116 public void ResetSelectionForeColor ()
2118 grid_style.SelectionForeColor = default_style.SelectionForeColor;
2121 public void Select (int row)
2125 if (selected_rows.Count == 0)
2126 selection_start = row;
2129 // UIA Framework: To raise event only when selecting
2130 bool wasSelected = rows [row].IsSelected;
2133 selected_rows[row] = true;
2134 rows[row].IsSelected = true;
2136 InvalidateRow (row);
2141 OnUIASelectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, row));
2146 public void SetDataBinding (object dataSource, string dataMember)
2148 SetDataSource (dataSource, dataMember);
2151 protected virtual bool ShouldSerializeAlternatingBackColor ()
2153 return (grid_style.AlternatingBackColor != default_style.AlternatingBackColor);
2156 protected virtual bool ShouldSerializeBackgroundColor ()
2158 return (background_color != def_background_color);
2161 protected virtual bool ShouldSerializeCaptionBackColor ()
2163 return (caption_backcolor != def_caption_backcolor);
2166 protected virtual bool ShouldSerializeCaptionForeColor ()
2168 return caption_forecolor != def_caption_forecolor;
2171 protected virtual bool ShouldSerializeGridLineColor ()
2173 return grid_style.GridLineColor != default_style.GridLineColor;
2176 protected virtual bool ShouldSerializeHeaderBackColor ()
2178 return grid_style.HeaderBackColor != default_style.HeaderBackColor;
2181 protected bool ShouldSerializeHeaderFont ()
2183 return grid_style.HeaderFont != default_style.HeaderFont;
2186 protected virtual bool ShouldSerializeHeaderForeColor ()
2188 return grid_style.HeaderForeColor != default_style.HeaderForeColor;
2191 protected virtual bool ShouldSerializeLinkHoverColor ()
2193 return grid_style.LinkHoverColor != grid_style.LinkHoverColor;
2196 protected virtual bool ShouldSerializeParentRowsBackColor ()
2198 return parent_rows_backcolor != def_parent_rows_backcolor;
2201 protected virtual bool ShouldSerializeParentRowsForeColor ()
2203 return parent_rows_backcolor != def_parent_rows_backcolor;
2206 protected bool ShouldSerializePreferredRowHeight ()
2208 return grid_style.PreferredRowHeight != default_style.PreferredRowHeight;
2211 protected bool ShouldSerializeSelectionBackColor ()
2213 return grid_style.SelectionBackColor != default_style.SelectionBackColor;
2216 protected virtual bool ShouldSerializeSelectionForeColor ()
2218 return grid_style.SelectionForeColor != default_style.SelectionForeColor;
2221 public void SubObjectsSiteChange (bool site)
2225 public void UnSelect (int row)
2228 // UIA Framework: To raise event only when unselecting
2229 bool wasSelected = rows [row].IsSelected;
2232 rows[row].IsSelected = false;
2233 selected_rows.Remove (row);
2234 InvalidateRow (row);
2237 // UIA Framework: Raises selection event
2239 OnUIASelectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, row));
2242 #endregion // Public Instance Methods
2244 #region Private Instance Methods
2246 internal void CalcAreasAndInvalidate ()
2252 private void ConnectListManagerEvents ()
2254 list_manager.MetaDataChanged += new EventHandler (OnListManagerMetaDataChanged);
2255 list_manager.PositionChanged += new EventHandler (OnListManagerPositionChanged);
2256 list_manager.ItemChanged += new ItemChangedEventHandler (OnListManagerItemChanged);
2259 private void DisconnectListManagerEvents ()
2261 list_manager.MetaDataChanged -= new EventHandler (OnListManagerMetaDataChanged);
2262 list_manager.PositionChanged -= new EventHandler (OnListManagerPositionChanged);
2263 list_manager.ItemChanged -= new ItemChangedEventHandler (OnListManagerItemChanged);
2266 void DisconnectTableStyleEvents ()
2268 current_style.AllowSortingChanged -= new EventHandler (TableStyleChanged);
2269 current_style.AlternatingBackColorChanged -= new EventHandler (TableStyleChanged);
2270 current_style.BackColorChanged -= new EventHandler (TableStyleChanged);
2271 current_style.ColumnHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2272 current_style.ForeColorChanged -= new EventHandler (TableStyleChanged);
2273 current_style.GridLineColorChanged -= new EventHandler (TableStyleChanged);
2274 current_style.GridLineStyleChanged -= new EventHandler (TableStyleChanged);
2275 current_style.HeaderBackColorChanged -= new EventHandler (TableStyleChanged);
2276 current_style.HeaderFontChanged -= new EventHandler (TableStyleChanged);
2277 current_style.HeaderForeColorChanged -= new EventHandler (TableStyleChanged);
2278 current_style.LinkColorChanged -= new EventHandler (TableStyleChanged);
2279 current_style.LinkHoverColorChanged -= new EventHandler (TableStyleChanged);
2280 current_style.MappingNameChanged -= new EventHandler (TableStyleChanged);
2281 current_style.PreferredColumnWidthChanged -= new EventHandler (TableStyleChanged);
2282 current_style.PreferredRowHeightChanged -= new EventHandler (TableStyleChanged);
2283 current_style.ReadOnlyChanged -= new EventHandler (TableStyleChanged);
2284 current_style.RowHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2285 current_style.RowHeaderWidthChanged -= new EventHandler (TableStyleChanged);
2286 current_style.SelectionBackColorChanged -= new EventHandler (TableStyleChanged);
2287 current_style.SelectionForeColorChanged -= new EventHandler (TableStyleChanged);
2290 void ConnectTableStyleEvents ()
2292 current_style.AllowSortingChanged += new EventHandler (TableStyleChanged);
2293 current_style.AlternatingBackColorChanged += new EventHandler (TableStyleChanged);
2294 current_style.BackColorChanged += new EventHandler (TableStyleChanged);
2295 current_style.ColumnHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2296 current_style.ForeColorChanged += new EventHandler (TableStyleChanged);
2297 current_style.GridLineColorChanged += new EventHandler (TableStyleChanged);
2298 current_style.GridLineStyleChanged += new EventHandler (TableStyleChanged);
2299 current_style.HeaderBackColorChanged += new EventHandler (TableStyleChanged);
2300 current_style.HeaderFontChanged += new EventHandler (TableStyleChanged);
2301 current_style.HeaderForeColorChanged += new EventHandler (TableStyleChanged);
2302 current_style.LinkColorChanged += new EventHandler (TableStyleChanged);
2303 current_style.LinkHoverColorChanged += new EventHandler (TableStyleChanged);
2304 current_style.MappingNameChanged += new EventHandler (TableStyleChanged);
2305 current_style.PreferredColumnWidthChanged += new EventHandler (TableStyleChanged);
2306 current_style.PreferredRowHeightChanged += new EventHandler (TableStyleChanged);
2307 current_style.ReadOnlyChanged += new EventHandler (TableStyleChanged);
2308 current_style.RowHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2309 current_style.RowHeaderWidthChanged += new EventHandler (TableStyleChanged);
2310 current_style.SelectionBackColorChanged += new EventHandler (TableStyleChanged);
2311 current_style.SelectionForeColorChanged += new EventHandler (TableStyleChanged);
2314 void TableStyleChanged (object sender, EventArgs args)
2317 CalcAreasAndInvalidate ();
2321 private void EnsureCellVisibility (DataGridCell cell)
2323 if (cell.ColumnNumber <= first_visible_column ||
2324 cell.ColumnNumber + 1 >= first_visible_column + visible_column_count) {
2326 first_visible_column = GetFirstColumnForColumnVisibility (first_visible_column, cell.ColumnNumber);
2327 int pixel = GetColumnStartingPixel (first_visible_column);
2328 ScrollToColumnInPixels (pixel);
2329 horiz_scrollbar.Value = pixel;
2333 if (cell.RowNumber < first_visible_row ||
2334 cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2336 if (cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2337 int old_first_visible_row = first_visible_row;
2338 first_visible_row = 1 + cell.RowNumber - visible_row_count;
2339 UpdateVisibleRowCount ();
2340 ScrollToRow (old_first_visible_row, first_visible_row);
2342 int old_first_visible_row = first_visible_row;
2343 first_visible_row = cell.RowNumber;
2344 UpdateVisibleRowCount ();
2345 ScrollToRow (old_first_visible_row, first_visible_row);
2348 vert_scrollbar.Value = first_visible_row;
2352 private void SetDataSource (object source, string member)
2354 SetDataSource (source, member, true);
2357 bool in_setdatasource;
2358 private void SetDataSource (object source, string member, bool recreate_rows)
2360 CurrencyManager old_lm = list_manager;
2362 /* we need this bool flag to work around a
2363 * problem with OnBindingContextChanged. once
2364 * that stuff works properly, remove this
2366 if (in_setdatasource)
2368 in_setdatasource = true;
2371 if (datasource == source && member == datamember)
2375 if (source != null && source as IListSource != null && source as IList != null)
2376 throw new Exception ("Wrong complex data binding source");
2378 datasource = source;
2379 datamember = member;
2384 current_cell = new DataGridCell ();
2386 if (list_manager != null)
2387 DisconnectListManagerEvents ();
2389 list_manager = null;
2391 /* create the new list manager */
2392 if (BindingContext != null && datasource != null)
2393 list_manager = (CurrencyManager) BindingContext [datasource, datamember];
2395 if (list_manager != null)
2396 ConnectListManagerEvents ();
2398 if (old_lm != list_manager) {
2401 /* reset first_visible_row to 0 here before
2402 * doing anything that'll requires us to
2403 * figure out if we need a scrollbar. */
2404 vert_scrollbar.Value = 0;
2405 horiz_scrollbar.Value = 0;
2406 first_visible_row = 0;
2409 RecreateDataGridRows (false);
2412 CalcAreasAndInvalidate ();
2414 in_setdatasource = false;
2416 OnDataSourceChanged (EventArgs.Empty);
2419 void RecreateDataGridRows (bool recalc)
2421 DataGridRelationshipRow[] new_rows = new DataGridRelationshipRow[RowsCount + (ShowEditRow ? 1 : 0)];
2422 int start_index = 0;
2424 start_index = rows.Length;
2425 Array.Copy (rows, 0, new_rows, 0, rows.Length < new_rows.Length ? rows.Length : new_rows.Length);
2428 for (int i = start_index; i < new_rows.Length; i ++) {
2429 new_rows[i] = new DataGridRelationshipRow (this);
2430 new_rows[i].height = RowHeight;
2432 new_rows[i].VerticalOffset = new_rows[i-1].VerticalOffset + new_rows[i-1].Height;
2436 // UIA Framework event: Updates collection list depending on binding
2437 CollectionChangeAction action = CollectionChangeAction.Refresh;
2439 if (new_rows.Length - rows.Length > 0)
2440 action = CollectionChangeAction.Add;
2442 action = CollectionChangeAction.Remove;
2448 CalcAreasAndInvalidate ();
2450 // UIA Framework event: Row added/removed
2451 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (action, -1));
2455 internal void UpdateRowsFrom (DataGridRelationshipRow row)
2457 int start_index = Array.IndexOf (rows, row);
2458 if (start_index == -1)
2461 for (int i = start_index + 1; i < rows.Length; i ++)
2462 rows[i].VerticalOffset = rows[i-1].VerticalOffset + rows[i-1].Height;
2464 CalcAreasAndInvalidate ();
2469 if (list_manager != null) {
2470 string list_name = list_manager.GetListName (null);
2471 if (TableStyles[list_name] == null) {
2472 // no style exists by the supplied name
2473 current_style.GridColumnStyles.Clear ();
2474 current_style.CreateColumnsForTable (false);
2475 } else if (CurrentTableStyle == grid_style ||
2476 CurrentTableStyle.MappingName != list_name) {
2477 // If the style has been defined by the user, use it
2478 // Also, if the user provided style is empty,
2479 // force a bind for it
2480 CurrentTableStyle = styles_collection[list_name];
2481 current_style.CreateColumnsForTable (current_style.GridColumnStyles.Count > 0);
2483 current_style.CreateColumnsForTable (true);
2486 current_style.CreateColumnsForTable (false);
2489 private void OnListManagerMetaDataChanged (object sender, EventArgs e)
2492 CalcAreasAndInvalidate ();
2495 private void OnListManagerPositionChanged (object sender, EventArgs e)
2497 from_positionchanged_handler = true;
2498 CurrentRow = list_manager.Position;
2499 from_positionchanged_handler = false;
2502 private void OnListManagerItemChanged (object sender, ItemChangedEventArgs e)
2504 if (e.Index == -1) {
2506 if (rows == null || RowsCount != rows.Length - (ShowEditRow ? 1 : 0))
2507 RecreateDataGridRows (true);
2509 InvalidateRow (e.Index);
2513 private void OnTableStylesCollectionChanged (object sender, CollectionChangeEventArgs e)
2515 if (ListManager == null)
2518 string list_name = ListManager.GetListName (null);
2520 case CollectionChangeAction.Add:
2521 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2522 CurrentTableStyle = (DataGridTableStyle)e.Element;
2523 // force to auto detect columns in case the new style is completely empty
2524 ((DataGridTableStyle) e.Element).CreateColumnsForTable (CurrentTableStyle.GridColumnStyles.Count > 0);
2527 case CollectionChangeAction.Remove:
2528 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2529 CurrentTableStyle = default_style;
2530 current_style.GridColumnStyles.Clear ();
2531 current_style.CreateColumnsForTable (false);
2534 case CollectionChangeAction.Refresh:
2535 if (CurrentTableStyle == default_style
2536 || String.Compare (list_name, CurrentTableStyle.MappingName, true) != 0) {
2537 DataGridTableStyle style = styles_collection [list_name];
2538 if (style != null) {
2539 CurrentTableStyle = style;
2540 current_style.CreateColumnsForTable (false);
2542 CurrentTableStyle = default_style;
2543 current_style.GridColumnStyles.Clear ();
2544 current_style.CreateColumnsForTable (false);
2549 CalcAreasAndInvalidate ();
2552 internal void AddNewRow ()
2554 ListManager.EndCurrentEdit ();
2555 ListManager.AddNew ();
2558 private void Edit ()
2560 if (CurrentTableStyle.GridColumnStyles.Count == 0)
2563 if (!CurrentTableStyle.GridColumnStyles[CurrentColumn].bound)
2566 if (ListManager != null && ListManager.Count == 0)
2570 is_changing = false;
2572 CurrentTableStyle.GridColumnStyles[CurrentColumn].Edit (ListManager,
2573 CurrentRow, GetCellBounds (CurrentRow, CurrentColumn),
2574 _readonly, null, true);
2577 private void EndEdit ()
2579 if (CurrentTableStyle.GridColumnStyles.Count == 0)
2582 if (!CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].bound)
2585 EndEdit (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber],
2586 current_cell.RowNumber, false);
2589 private void ShiftSelection (int index)
2591 // we have to save off selection_start
2592 // because ResetSelection clobbers it
2593 int saved_selection_start = selection_start;
2597 selection_start = saved_selection_start;
2599 if (index >= selection_start) {
2600 start = selection_start;
2604 end = selection_start;
2607 if (start == -1) start = 0;
2609 for (int idx = start; idx <= end; idx ++)
2613 private void ScrollToColumnInPixels (int pixel)
2617 if (pixel > horiz_pixeloffset) // ScrollRight
2618 pixels = -1 * (pixel - horiz_pixeloffset);
2620 pixels = horiz_pixeloffset - pixel;
2622 Rectangle area = cells_area;
2624 if (ColumnHeadersVisible) {
2625 area.Y -= ColumnHeadersArea.Height;
2626 area.Height += ColumnHeadersArea.Height;
2629 horiz_pixeloffset = pixel;
2630 UpdateVisibleColumn ();
2634 XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
2636 int pixel_offset = GetColumnStartingPixel (CurrentColumn);
2637 int next_pixel_offset = pixel_offset + CurrentTableStyle.GridColumnStyles[CurrentColumn].Width;
2639 if (pixel_offset >= horiz_pixeloffset
2640 && next_pixel_offset < horiz_pixeloffset + cells_area.Width)
2644 private void ScrollToRow (int old_row, int new_row)
2649 if (new_row > old_row) { // Scrolldown
2650 for (i = old_row; i < new_row; i ++)
2651 pixels -= rows[i].Height;
2653 for (i = new_row; i < old_row; i ++)
2654 pixels += rows[i].Height;
2662 Rectangle rows_area = cells_area; // Cells area - partial rows space
2664 if (RowHeadersVisible) {
2665 rows_area.X -= RowHeaderWidth;
2666 rows_area.Width += RowHeaderWidth;
2669 /* scroll the window */
2670 XplatUI.ScrollWindow (Handle, rows_area, 0, pixels, false);
2672 /* if the row is still */
2673 if (CurrentRow >= first_visible_row && CurrentRow < first_visible_row + visible_row_count)
2678 private void ColumnResize (int column)
2680 CurrencyManager source = this.ListManager;
2681 DataGridColumnStyle style = CurrentTableStyle.GridColumnStyles[column];
2682 string headerText = style.HeaderText;
2683 using (Graphics g = base.CreateGraphics ()) {
2684 int rows = source.Count;
2685 int width = (int)g.MeasureString (headerText, CurrentTableStyle.HeaderFont).Width + 4;
2687 for (int i = 0; i < rows; i++) {
2688 int rowColWidth = (int)style.GetPreferredSize (g, style.GetColumnValueAtRow (source, i)).Width;
2689 if (rowColWidth > width)
2690 width = rowColWidth;
2692 if (style.Width != width)
2693 style.Width = width;
2697 private void RowResize (int row)
2699 CurrencyManager source = this.ListManager;
2700 using (Graphics g = base.CreateGraphics ()) {
2701 GridColumnStylesCollection columns = CurrentTableStyle.GridColumnStyles;
2702 int colCount = columns.Count;
2703 //int rowCount = source.Count;
2705 for (int i = 0; i < colCount; i++) {
2706 object val = columns[i].GetColumnValueAtRow (source, row);
2707 height = Math.Max (columns[i].GetPreferredHeight (g, val), height);
2709 if (this.DataGridRows[row].Height != height)
2710 this.DataGridRows[row].Height = height;
2713 #endregion Private Instance Methods
2716 static object AllowNavigationChangedEvent = new object ();
2717 static object BackButtonClickEvent = new object ();
2718 static object BackgroundColorChangedEvent = new object ();
2719 static object BorderStyleChangedEvent = new object ();
2720 static object CaptionVisibleChangedEvent = new object ();
2721 static object CurrentCellChangedEvent = new object ();
2722 static object DataSourceChangedEvent = new object ();
2723 static object FlatModeChangedEvent = new object ();
2724 static object NavigateEvent = new object ();
2725 static object ParentRowsLabelStyleChangedEvent = new object ();
2726 static object ParentRowsVisibleChangedEvent = new object ();
2727 static object ReadOnlyChangedEvent = new object ();
2728 static object RowHeaderClickEvent = new object ();
2729 static object ScrollEvent = new object ();
2730 static object ShowParentDetailsButtonClickEvent = new object ();
2732 public event EventHandler AllowNavigationChanged {
2733 add { Events.AddHandler (AllowNavigationChangedEvent, value); }
2734 remove { Events.RemoveHandler (AllowNavigationChangedEvent, value); }
2737 public event EventHandler BackButtonClick {
2738 add { Events.AddHandler (BackButtonClickEvent, value); }
2739 remove { Events.RemoveHandler (BackButtonClickEvent, value); }
2742 public event EventHandler BackgroundColorChanged {
2743 add { Events.AddHandler (BackgroundColorChangedEvent, value); }
2744 remove { Events.RemoveHandler (BackgroundColorChangedEvent, value); }
2748 [EditorBrowsable(EditorBrowsableState.Never)]
2749 public new event EventHandler BackgroundImageChanged {
2750 add { base.BackgroundImageChanged += value; }
2751 remove { base.BackgroundImageChanged -= value; }
2756 [EditorBrowsable(EditorBrowsableState.Never)]
2757 public new event EventHandler BackgroundImageLayoutChanged {
2758 add { base.BackgroundImageLayoutChanged += value; }
2759 remove { base.BackgroundImageLayoutChanged -= value; }
2764 [EditorBrowsable(EditorBrowsableState.Never)]
2765 public new event EventHandler TextChanged {
2766 add { base.TextChanged += value; }
2767 remove { base.TextChanged -= value; }
2771 [EditorBrowsable(EditorBrowsableState.Never)]
2772 public new event EventHandler CursorChanged {
2773 add { base.CursorChanged += value; }
2774 remove { base.CursorChanged -= value; }
2777 public event EventHandler BorderStyleChanged {
2778 add { Events.AddHandler (BorderStyleChangedEvent, value); }
2779 remove { Events.RemoveHandler (BorderStyleChangedEvent, value); }
2782 public event EventHandler CaptionVisibleChanged {
2783 add { Events.AddHandler (CaptionVisibleChangedEvent, value); }
2784 remove { Events.RemoveHandler (CaptionVisibleChangedEvent, value); }
2787 public event EventHandler CurrentCellChanged {
2788 add { Events.AddHandler (CurrentCellChangedEvent, value); }
2789 remove { Events.RemoveHandler (CurrentCellChangedEvent, value); }
2792 public event EventHandler DataSourceChanged {
2793 add { Events.AddHandler (DataSourceChangedEvent, value); }
2794 remove { Events.RemoveHandler (DataSourceChangedEvent, value); }
2797 public event EventHandler FlatModeChanged {
2798 add { Events.AddHandler (FlatModeChangedEvent, value); }
2799 remove { Events.RemoveHandler (FlatModeChangedEvent, value); }
2802 public event NavigateEventHandler Navigate {
2803 add { Events.AddHandler (NavigateEvent, value); }
2804 remove { Events.RemoveHandler (NavigateEvent, value); }
2807 public event EventHandler ParentRowsLabelStyleChanged {
2808 add { Events.AddHandler (ParentRowsLabelStyleChangedEvent, value); }
2809 remove { Events.RemoveHandler (ParentRowsLabelStyleChangedEvent, value); }
2812 public event EventHandler ParentRowsVisibleChanged {
2813 add { Events.AddHandler (ParentRowsVisibleChangedEvent, value); }
2814 remove { Events.RemoveHandler (ParentRowsVisibleChangedEvent, value); }
2817 public event EventHandler ReadOnlyChanged {
2818 add { Events.AddHandler (ReadOnlyChangedEvent, value); }
2819 remove { Events.RemoveHandler (ReadOnlyChangedEvent, value); }
2822 protected event EventHandler RowHeaderClick {
2823 add { Events.AddHandler (RowHeaderClickEvent, value); }
2824 remove { Events.RemoveHandler (RowHeaderClickEvent, value); }
2827 public event EventHandler Scroll {
2828 add { Events.AddHandler (ScrollEvent, value); }
2829 remove { Events.RemoveHandler (ScrollEvent, value); }
2832 public event EventHandler ShowParentDetailsButtonClick {
2833 add { Events.AddHandler (ShowParentDetailsButtonClickEvent, value); }
2834 remove { Events.RemoveHandler (ShowParentDetailsButtonClickEvent, value); }
2836 #endregion // Events
2838 #region Code originally in DataGridDrawingLogic.cs
2840 #region Local Variables
2843 Rectangle parent_rows;
2844 int width_of_all_columns;
2846 internal Rectangle caption_area;
2847 internal Rectangle column_headers_area; // Used columns header area
2848 internal int column_headers_max_width; // Total width (max width) for columns headrs
2849 internal Rectangle row_headers_area; // Used Headers rows area
2850 internal Rectangle cells_area;
2851 #endregion // Local Variables
2853 #region Public Instance Methods
2855 // Calc the max with of all columns
2856 private int CalcAllColumnsWidth ()
2859 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2861 for (int col = 0; col < cnt; col++) {
2862 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2865 width += CurrentTableStyle.GridColumnStyles[col].Width;
2870 // Gets a column from a pixel
2871 private int FromPixelToColumn (int pixel, out int column_x)
2874 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2880 if (CurrentTableStyle.CurrentRowHeadersVisible) {
2881 width += row_headers_area.X + row_headers_area.Width;
2882 column_x += row_headers_area.X + row_headers_area.Width;
2887 for (int col = 0; col < cnt; col++) {
2888 if (CurrentTableStyle.GridColumnStyles[col].bound == false)
2891 width += CurrentTableStyle.GridColumnStyles[col].Width;
2896 column_x += CurrentTableStyle.GridColumnStyles[col].Width;
2902 internal int GetColumnStartingPixel (int my_col)
2905 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2907 for (int col = 0; col < cnt; col++) {
2908 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2915 width += CurrentTableStyle.GridColumnStyles[col].Width;
2921 // Which column has to be the first visible column to ensure a column visibility
2922 int GetFirstColumnForColumnVisibility (int current_first_visible_column, int column)
2924 int new_col = column;
2927 if (column > current_first_visible_column) { // Going forward
2928 for (new_col = column; new_col >= 0; new_col--) {
2929 if (!CurrentTableStyle.GridColumnStyles[new_col].bound)
2931 width += CurrentTableStyle.GridColumnStyles[new_col].Width;
2933 if (width >= cells_area.Width)
2935 //return new_col < CurrentTableStyle.GridColumnStyles.Count ? new_col + 1 : CurrentTableStyle.GridColumnStyles.Count;
2943 bool in_calc_grid_areas;
2944 void CalcGridAreas ()
2946 if (!IsHandleCreated) // Delay calculations until the handle is created
2949 /* make sure we don't happen to end up in this method again */
2950 if (in_calc_grid_areas)
2953 in_calc_grid_areas = true;
2955 /* Order is important. E.g. row headers max. height depends on caption */
2956 horiz_pixeloffset = 0;
2959 CalcParentButtons ();
2960 UpdateVisibleRowCount ();
2962 width_of_all_columns = CalcAllColumnsWidth ();
2963 CalcColumnHeaders ();
2966 bool needHoriz = false;
2967 bool needVert = false;
2969 /* figure out which scrollbars we need, and what the visible areas are */
2970 int visible_cells_width = cells_area.Width;
2971 int visible_cells_height = cells_area.Height;
2972 int allrows = RowsCount;
2974 if (ShowEditRow && RowsCount > 0)
2977 /* use a loop to iteratively calculate whether
2978 * we need horiz/vert scrollbars. */
2979 for (int i = 0; i < 3; i++) {
2981 visible_cells_width = cells_area.Width - vert_scrollbar.Width;
2983 visible_cells_height = cells_area.Height - horiz_scrollbar.Height;
2985 UpdateVisibleRowCount ();
2987 needHoriz = (width_of_all_columns > visible_cells_width);
2988 needVert = (allrows > visible_row_count);
2991 int horiz_scrollbar_width = ClientRectangle.Width;
2992 int horiz_scrollbar_maximum = 0;
2993 int vert_scrollbar_height = 0;
2994 int vert_scrollbar_maximum = 0;
2997 SetUpVerticalScrollBar (out vert_scrollbar_height, out vert_scrollbar_maximum);
3000 SetUpHorizontalScrollBar (out horiz_scrollbar_maximum);
3002 cells_area.Width = visible_cells_width;
3003 cells_area.Height = visible_cells_height;
3005 if (needVert && needHoriz) {
3007 parent_rows.Width -= vert_scrollbar.Width;
3009 if (!ColumnHeadersVisible) {
3010 if (column_headers_area.X + column_headers_area.Width > vert_scrollbar.Location.X) {
3011 column_headers_area.Width -= vert_scrollbar.Width;
3015 horiz_scrollbar_width -= vert_scrollbar.Width;
3016 vert_scrollbar_height -= horiz_scrollbar.Height;
3020 if (row_headers_area.Y + row_headers_area.Height > ClientRectangle.Y + ClientRectangle.Height) {
3021 row_headers_area.Height -= horiz_scrollbar.Height;
3024 vert_scrollbar.Size = new Size (vert_scrollbar.Width,
3025 vert_scrollbar_height);
3027 vert_scrollbar.Maximum = vert_scrollbar_maximum;
3028 Controls.Add (vert_scrollbar);
3029 vert_scrollbar.Visible = true;
3031 Controls.Remove (vert_scrollbar);
3032 vert_scrollbar.Visible = false;
3036 horiz_scrollbar.Size = new Size (horiz_scrollbar_width,
3037 horiz_scrollbar.Height);
3039 horiz_scrollbar.Maximum = horiz_scrollbar_maximum;
3040 Controls.Add (horiz_scrollbar);
3041 horiz_scrollbar.Visible = true;
3043 Controls.Remove (horiz_scrollbar);
3044 horiz_scrollbar.Visible = false;
3047 UpdateVisibleColumn ();
3048 UpdateVisibleRowCount ();
3050 in_calc_grid_areas = false;
3055 caption_area.X = ClientRectangle.X;
3056 caption_area.Y = ClientRectangle.Y;
3057 caption_area.Width = ClientRectangle.Width;
3058 if (caption_visible) {
3059 caption_area.Height = CaptionFont.Height;
3060 if (caption_area.Height < back_button_image.Height)
3061 caption_area.Height = back_button_image.Height;
3062 caption_area.Height += 2;
3064 caption_area.Height = 0;
3067 void CalcCellsArea ()
3069 cells_area.X = ClientRectangle.X + row_headers_area.Width;
3070 cells_area.Y = column_headers_area.Y + column_headers_area.Height;
3071 cells_area.Width = ClientRectangle.X + ClientRectangle.Width - cells_area.X;
3072 if (cells_area.Width < 0)
3073 cells_area.Width = 0;
3074 cells_area.Height = ClientRectangle.Y + ClientRectangle.Height - cells_area.Y;
3075 if (cells_area.Height < 0)
3076 cells_area.Height = 0;
3079 void CalcColumnHeaders ()
3083 column_headers_area.X = ClientRectangle.X;
3084 column_headers_area.Y = parent_rows.Y + parent_rows.Height;
3086 // TODO: take into account Scrollbars
3087 column_headers_max_width = ClientRectangle.X + ClientRectangle.Width - column_headers_area.X;
3088 max_width_cols = column_headers_max_width;
3090 if (CurrentTableStyle.CurrentRowHeadersVisible)
3091 max_width_cols -= RowHeaderWidth;
3093 if (width_of_all_columns > max_width_cols) {
3094 column_headers_area.Width = column_headers_max_width;
3096 column_headers_area.Width = width_of_all_columns;
3098 if (CurrentTableStyle.CurrentRowHeadersVisible)
3099 column_headers_area.Width += RowHeaderWidth;
3102 if (ColumnHeadersVisible)
3103 column_headers_area.Height = CurrentTableStyle.HeaderFont.Height + 6;
3105 column_headers_area.Height = 0;
3108 void CalcParentRows ()
3110 parent_rows.X = ClientRectangle.X;
3111 parent_rows.Y = caption_area.Y + caption_area.Height;
3112 parent_rows.Width = ClientRectangle.Width;
3114 parent_rows.Height = (CaptionFont.Height + 3) * data_source_stack.Count;
3116 parent_rows.Height = 0;
3119 void CalcParentButtons ()
3121 if (data_source_stack.Count > 0 && CaptionVisible) {
3122 back_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - 2 * (caption_area.Height - 2) - 8,
3123 caption_area.Height / 2 - back_button_image.Height / 2,
3124 back_button_image.Width, back_button_image.Height);
3125 parent_rows_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - (caption_area.Height - 2) - 4,
3126 caption_area.Height / 2 - parent_rows_button_image.Height / 2,
3127 parent_rows_button_image.Width, parent_rows_button_image.Height);
3129 back_button_rect = parent_rows_button_rect = Rectangle.Empty;
3133 void CalcRowHeaders ()
3135 row_headers_area.X = ClientRectangle.X;
3136 row_headers_area.Y = column_headers_area.Y + column_headers_area.Height;
3137 row_headers_area.Height = ClientRectangle.Height + ClientRectangle.Y - row_headers_area.Y;
3139 if (CurrentTableStyle.CurrentRowHeadersVisible)
3140 row_headers_area.Width = RowHeaderWidth;
3142 row_headers_area.Width = 0;
3145 int GetVisibleRowCount (int visibleHeight)
3147 int rows_height = 0;
3149 for (r = FirstVisibleRow; r < rows.Length; r ++) {
3150 if (rows_height + rows[r].Height >= visibleHeight)
3152 rows_height += rows[r].Height;
3155 if (r <= rows.Length - 1)
3158 return r - FirstVisibleRow;
3161 void UpdateVisibleColumn ()
3163 visible_column_count = 0;
3165 if (CurrentTableStyle.GridColumnStyles.Count == 0)
3173 min_pixel = horiz_pixeloffset;
3174 if (CurrentTableStyle.CurrentRowHeadersVisible)
3175 min_pixel += row_headers_area.X + row_headers_area.Width;
3176 max_pixel = min_pixel + cells_area.Width;
3178 first_visible_column = FromPixelToColumn (min_pixel, out unused);
3179 max_col = FromPixelToColumn (max_pixel, out unused);
3181 for (int i = first_visible_column; i <= max_col; i ++) {
3182 if (CurrentTableStyle.GridColumnStyles[i].bound)
3183 visible_column_count++;
3186 if (first_visible_column + visible_column_count < CurrentTableStyle.GridColumnStyles.Count) {
3187 visible_column_count++; // Partially visible column
3191 void UpdateVisibleRowCount ()
3193 visible_row_count = GetVisibleRowCount (cells_area.Height);
3195 CalcRowHeaders (); // Height depends on num of visible rows
3198 void InvalidateCaption ()
3200 if (caption_area.IsEmpty)
3203 Invalidate (caption_area);
3206 void InvalidateRow (int row)
3208 if (row < FirstVisibleRow || row > FirstVisibleRow + VisibleRowCount)
3211 Rectangle rect_row = new Rectangle ();
3213 rect_row.X = cells_area.X;
3214 rect_row.Width = width_of_all_columns;
3215 if (rect_row.Width > cells_area.Width)
3216 rect_row.Width = cells_area.Width;
3217 rect_row.Height = rows[row].Height;
3218 rect_row.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3219 Invalidate (rect_row);
3222 void InvalidateRowHeader (int row)
3224 Rectangle rect_rowhdr = new Rectangle ();
3225 rect_rowhdr.X = row_headers_area.X;
3226 rect_rowhdr.Width = row_headers_area.Width;
3227 rect_rowhdr.Height = rows[row].Height;
3228 rect_rowhdr.Y = row_headers_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3229 Invalidate (rect_rowhdr);
3232 internal void InvalidateColumn (DataGridColumnStyle column)
3234 Rectangle rect_col = new Rectangle ();
3238 col = CurrentTableStyle.GridColumnStyles.IndexOf (column);
3243 rect_col.Width = column.Width;
3244 col_pixel = GetColumnStartingPixel (col);
3245 rect_col.X = cells_area.X + col_pixel - horiz_pixeloffset;
3246 rect_col.Y = cells_area.Y;
3247 rect_col.Height = cells_area.Height;
3248 Invalidate (rect_col);
3251 void DrawResizeLineVert (int x)
3253 XplatUI.DrawReversibleRectangle (Handle,
3254 new Rectangle (x, cells_area.Y, 1, cells_area.Height - 3),
3258 void DrawResizeLineHoriz (int y)
3260 XplatUI.DrawReversibleRectangle (Handle,
3261 new Rectangle (cells_area.X, y, cells_area.Width - 3, 1),
3265 void SetUpHorizontalScrollBar (out int maximum)
3267 maximum = width_of_all_columns;
3269 horiz_scrollbar.Location = new Point (ClientRectangle.X, ClientRectangle.Y +
3270 ClientRectangle.Height - horiz_scrollbar.Height);
3272 horiz_scrollbar.LargeChange = cells_area.Width;
3275 void SetUpVerticalScrollBar (out int height, out int maximum)
3279 y = ClientRectangle.Y + parent_rows.Y + parent_rows.Height;
3280 height = ClientRectangle.Height - parent_rows.Y - parent_rows.Height;
3282 vert_scrollbar.Location = new Point (ClientRectangle.X +
3283 ClientRectangle.Width - vert_scrollbar.Width, y);
3285 maximum = RowsCount;
3287 if (ShowEditRow && RowsCount > 0) {
3291 vert_scrollbar.LargeChange = VLargeChange;
3294 #endregion // Public Instance Methods
3296 #region Instance Properties
3297 // Returns the ColumnHeaders area excluding the rectangle shared with RowHeaders
3298 internal Rectangle ColumnHeadersArea {
3300 Rectangle columns_area = column_headers_area;
3302 if (CurrentTableStyle.CurrentRowHeadersVisible) {
3303 columns_area.X += RowHeaderWidth;
3304 columns_area.Width -= RowHeaderWidth;
3306 return columns_area;
3310 internal Rectangle RowHeadersArea {
3311 get { return row_headers_area; }
3314 internal Rectangle ParentRowsArea {
3315 get { return parent_rows; }
3319 get { return VisibleRowCount; }
3322 #endregion Instance Properties
3324 #endregion // Code originally in DataGridDrawingLogic.cs
3328 #region UIA Framework: Methods, Properties and Events
3330 static object UIACollectionChangedEvent = new object ();
3331 static object UIASelectionChangedEvent = new object ();
3332 static object UIAColumnHeadersVisibleChangedEvent = new object ();
3333 static object UIAGridCellChangedEvent = new object ();
3335 internal ScrollBar UIAHScrollBar {
3336 get { return horiz_scrollbar; }
3339 internal ScrollBar UIAVScrollBar {
3340 get { return vert_scrollbar; }
3343 internal DataGridTableStyle UIACurrentTableStyle {
3344 get { return current_style; }
3347 internal int UIASelectedRows {
3348 get { return selected_rows.Count; }
3351 internal Rectangle UIAColumnHeadersArea {
3352 get { return ColumnHeadersArea; }
3355 internal Rectangle UIACaptionArea {
3356 get { return caption_area; }
3359 internal Rectangle UIACellsArea {
3360 get { return cells_area; }
3363 internal int UIARowHeight {
3364 get { return RowHeight; }
3367 internal event CollectionChangeEventHandler UIACollectionChanged {
3368 add { Events.AddHandler (UIACollectionChangedEvent, value); }
3369 remove { Events.RemoveHandler (UIACollectionChangedEvent, value); }
3372 internal event CollectionChangeEventHandler UIASelectionChanged {
3373 add { Events.AddHandler (UIASelectionChangedEvent, value); }
3374 remove { Events.RemoveHandler (UIASelectionChangedEvent, value); }
3377 internal event EventHandler UIAColumnHeadersVisibleChanged {
3378 add { Events.AddHandler (UIAColumnHeadersVisibleChangedEvent, value); }
3379 remove { Events.RemoveHandler (UIAColumnHeadersVisibleChangedEvent, value); }
3382 internal event CollectionChangeEventHandler UIAGridCellChanged {
3383 add { Events.AddHandler (UIAGridCellChangedEvent, value); }
3384 remove { Events.RemoveHandler (UIAGridCellChangedEvent, value); }
3387 internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
3389 CollectionChangeEventHandler eh
3390 = (CollectionChangeEventHandler) Events [UIACollectionChangedEvent];
3395 internal void OnUIASelectionChangedEvent (CollectionChangeEventArgs args)
3397 CollectionChangeEventHandler eh
3398 = (CollectionChangeEventHandler) Events [UIASelectionChangedEvent];
3403 internal void OnUIAColumnHeadersVisibleChanged ()
3405 EventHandler eh = (EventHandler) Events [UIAColumnHeadersVisibleChangedEvent];
3407 eh (this, EventArgs.Empty);
3410 internal void OnUIAGridCellChanged (CollectionChangeEventArgs args)
3412 CollectionChangeEventHandler eh
3413 = (CollectionChangeEventHandler) Events [UIAGridCellChangedEvent];
3418 #endregion // UIA Framework: Methods, Properties and Events