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 Novell, Inc. (http://www.novell.com)
23 // Pedro MartÃnez Juliá <pedromj@gmail.com>
30 using System.ComponentModel;
32 using System.Windows.Forms.VisualStyles;
34 namespace System.Windows.Forms {
36 public class DataGridViewCheckBoxCell : DataGridViewCell, IDataGridViewEditingCell {
38 private object editingCellFormattedValue;
39 private bool editingCellValueChanged;
40 private object falseValue;
41 private FlatStyle flatStyle;
42 private object indeterminateValue;
43 private bool threeState;
44 private object trueValue;
45 // private Type valueType;
46 private PushButtonState check_state;
48 public DataGridViewCheckBoxCell ()
50 check_state = PushButtonState.Normal;
51 editingCellFormattedValue = false;
52 editingCellValueChanged = false;
54 flatStyle = FlatStyle.Standard;
55 indeterminateValue = null;
61 public DataGridViewCheckBoxCell (bool threeState) : this()
63 this.threeState = threeState;
64 editingCellFormattedValue = CheckState.Unchecked;
67 public virtual object EditingCellFormattedValue {
68 get { return editingCellFormattedValue; }
70 if (FormattedValueType == null || value == null || value.GetType() != FormattedValueType || !(value is Boolean) || !(value is CheckState)) {
71 throw new ArgumentException("Cannot set this property.");
73 editingCellFormattedValue = value;
77 public virtual bool EditingCellValueChanged {
78 get { return editingCellValueChanged; }
79 set { editingCellValueChanged = value; }
82 public override Type EditType {
87 public object FalseValue {
88 get { return falseValue; }
89 set { falseValue = value; }
92 [DefaultValue (FlatStyle.Standard)]
93 public FlatStyle FlatStyle {
94 get { return flatStyle; }
96 if (!Enum.IsDefined(typeof(FlatStyle), value)) {
97 throw new InvalidEnumArgumentException("Value is not valid FlatStyle.");
99 if (value == FlatStyle.Popup) {
100 throw new Exception("FlatStyle cannot be set to Popup in this control.");
105 public override Type FormattedValueType {
108 return typeof(CheckState);
110 return typeof(Boolean);
114 [DefaultValue (null)]
115 public object IndeterminateValue {
116 get { return indeterminateValue; }
117 set { indeterminateValue = value; }
120 [DefaultValue (false)]
121 public bool ThreeState {
122 get { return threeState; }
123 set { threeState = value; }
126 [DefaultValue (null)]
127 public object TrueValue {
128 get { return trueValue; }
129 set { trueValue = value; }
132 public override Type ValueType {
134 if (base.ValueType == null) {
135 if (OwningColumn != null && OwningColumn.ValueType != null) {
136 return OwningColumn.ValueType;
139 return typeof(CheckState);
141 return typeof(Boolean);
143 return base.ValueType;
145 set { base.ValueType = value; }
148 public override object Clone ()
150 DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell) base.Clone();
151 cell.editingCellValueChanged = this.editingCellValueChanged;
152 cell.editingCellFormattedValue = this.editingCellFormattedValue;
153 cell.falseValue = this.falseValue;
154 cell.flatStyle = this.flatStyle;
155 cell.indeterminateValue = this.indeterminateValue;
156 cell.threeState = this.threeState;
157 cell.trueValue = this.trueValue;
158 cell.ValueType = this.ValueType;
162 public virtual object GetEditingCellFormattedValue (DataGridViewDataErrorContexts context)
164 if (FormattedValueType == null) {
165 throw new InvalidOperationException("FormattedValueType is null.");
167 if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) {
168 return Convert.ToString(Value);
171 if (editingCellFormattedValue == null)
173 return CheckState.Indeterminate;
177 return editingCellFormattedValue;
180 public override object ParseFormattedValue (object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
182 if (cellStyle == null) {
183 throw new ArgumentNullException("CellStyle is null");
185 if (FormattedValueType == null) {
186 throw new FormatException("FormattedValueType is null.");
188 if (formattedValue == null || formattedValue.GetType() != FormattedValueType) {
189 throw new ArgumentException("FormattedValue is null or is not instance of FormattedValueType.");
192 return base.ParseFormattedValue (formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter);
195 public virtual void PrepareEditingCellForEdit (bool selectAll)
197 editingCellFormattedValue = GetCurrentValue ();
200 public override string ToString ()
202 return string.Format ("DataGridViewCheckBoxCell {{ ColumnIndex={0}, RowIndex={1} }}", ColumnIndex, RowIndex);
205 protected override bool ContentClickUnsharesRow (DataGridViewCellEventArgs e)
207 return this.IsInEditMode;
210 protected override bool ContentDoubleClickUnsharesRow (DataGridViewCellEventArgs e)
212 return this.IsInEditMode;
215 protected override AccessibleObject CreateAccessibilityInstance ()
217 return new DataGridViewCheckBoxCellAccessibleObject(this);
220 protected override Rectangle GetContentBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
222 if (DataGridView == null)
223 return Rectangle.Empty;
225 return new Rectangle ((Size.Width - 13) / 2, (Size.Height - 13) / 2, 13, 13);
228 protected override Rectangle GetErrorIconBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
230 if (DataGridView == null || string.IsNullOrEmpty (ErrorText))
231 return Rectangle.Empty;
233 Size error_icon = new Size (12, 11);
234 return new Rectangle (new Point (Size.Width - error_icon.Width - 5, (Size.Height - error_icon.Height) / 2), error_icon);
237 protected override object GetFormattedValue (object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
239 if (DataGridView == null || value == null)
241 return CheckState.Indeterminate;
248 protected override Size GetPreferredSize (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize)
250 return new Size (21, 20);
253 protected override bool KeyDownUnsharesRow (KeyEventArgs e, int rowIndex)
255 // true if the user pressed the SPACE key without modifier keys; otherwise, false
256 return e.KeyData == Keys.Space;
259 protected override bool KeyUpUnsharesRow (KeyEventArgs e, int rowIndex)
261 // true if the user released the SPACE key; otherwise false
262 return e.KeyData == Keys.Space;
265 protected override bool MouseDownUnsharesRow (DataGridViewCellMouseEventArgs e)
267 return (e.Button == MouseButtons.Left);
270 protected override bool MouseEnterUnsharesRow (int rowIndex)
272 // true if the cell was the last cell receiving a mouse click; otherwise, false.
276 protected override bool MouseLeaveUnsharesRow (int rowIndex)
278 // true if the button displayed by the cell is in the pressed state; otherwise, false.
279 return check_state == PushButtonState.Pressed;
282 protected override bool MouseUpUnsharesRow (DataGridViewCellMouseEventArgs e)
284 // true if the mouse up was caused by the release of the left mouse button; otherwise false.
285 return e.Button == MouseButtons.Left;
288 protected override void OnContentClick (DataGridViewCellEventArgs e)
294 DataGridView.BeginEdit (false);
299 private void ToggleCheckState ()
301 CheckState cs = GetCurrentValue ();
304 if (cs == CheckState.Indeterminate)
305 editingCellFormattedValue = CheckState.Unchecked;
306 else if (cs == CheckState.Checked)
307 editingCellFormattedValue = CheckState.Indeterminate;
309 editingCellFormattedValue = CheckState.Checked;
311 if (cs == CheckState.Checked)
312 editingCellFormattedValue = false;
314 editingCellFormattedValue = true;
317 editingCellValueChanged = true;
318 DataGridView.InvalidateCell (this);
321 protected override void OnContentDoubleClick (DataGridViewCellEventArgs e)
325 protected override void OnKeyDown (KeyEventArgs e, int rowIndex)
327 // when activated by the SPACE key, this method updates the cell's user interface
328 if (!ReadOnly && (e.KeyData & Keys.Space) == Keys.Space) {
329 check_state = PushButtonState.Pressed;
330 DataGridView.InvalidateCell (this);
334 protected override void OnKeyUp (KeyEventArgs e, int rowIndex)
336 // when activated by the SPACE key, this method updates the cell's user interface
337 if (!ReadOnly && (e.KeyData & Keys.Space) == Keys.Space) {
338 check_state = PushButtonState.Normal;
340 DataGridView.BeginEdit (false);
345 protected override void OnLeave (int rowIndex, bool throughMouseClick)
347 if (!ReadOnly && check_state != PushButtonState.Normal) {
348 check_state = PushButtonState.Normal;
349 DataGridView.InvalidateCell (this);
353 protected override void OnMouseDown (DataGridViewCellMouseEventArgs e)
355 // if activated by depresing the left mouse button, this method updates the cell's user interface
356 if (!ReadOnly && (e.Button & MouseButtons.Left) == MouseButtons.Left) {
357 check_state = PushButtonState.Pressed;
358 DataGridView.InvalidateCell (this);
362 protected override void OnMouseLeave (int rowIndex)
364 // if the cell's button is not in its normal state, this method causes the cell's user interface to be updated.
365 if (!ReadOnly && check_state != PushButtonState.Normal) {
366 check_state = PushButtonState.Normal;
367 DataGridView.InvalidateCell (this);
371 protected override void OnMouseMove (DataGridViewCellMouseEventArgs e)
373 if (!ReadOnly && check_state != PushButtonState.Normal && check_state != PushButtonState.Hot) {
374 check_state = PushButtonState.Hot;
375 DataGridView.InvalidateCell (this);
379 protected override void OnMouseUp (DataGridViewCellMouseEventArgs e)
381 // if activated by the left mouse button, this method updates the cell's user interface
382 if (!ReadOnly && (e.Button & MouseButtons.Left) == MouseButtons.Left) {
383 check_state = PushButtonState.Normal;
384 DataGridView.InvalidateCell (this);
388 protected override void Paint (Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
390 base.Paint (graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
393 internal override void PaintPartContent (Graphics graphics, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, object formattedValue)
396 CheckState value = GetCurrentValue ();
398 if ((CheckState)value == CheckState.Unchecked)
399 state = (CheckBoxState)check_state;
400 else if ((CheckState)value == CheckState.Checked)
401 state = (CheckBoxState)((int)check_state + 4);
403 state = (CheckBoxState)((int)check_state + 8);
405 state = (CheckBoxState)check_state;
407 Point p = new Point (cellBounds.X + (Size.Width - 13) / 2, cellBounds.Y + (Size.Height - 13) / 2);
408 CheckBoxRenderer.DrawCheckBox (graphics, p, state);
411 private CheckState GetCurrentValue ()
413 CheckState cs = CheckState.Indeterminate;
417 if (editingCellValueChanged)
418 current_obj = editingCellFormattedValue;
422 if (current_obj == null)
423 cs = CheckState.Indeterminate;
424 else if (current_obj is bool)
426 if ((bool)current_obj == true)
427 cs = CheckState.Checked;
428 else if ((bool)current_obj == false)
429 cs = CheckState.Unchecked;
431 else if (current_obj is CheckState)
432 cs = (CheckState)current_obj;
437 protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject {
439 public DataGridViewCheckBoxCellAccessibleObject (DataGridViewCell owner) : base(owner)
443 public override string DefaultAction {
445 if (Owner.ReadOnly) {
448 // return "Press to check" if the check box is not selected
449 // and "Press to uncheck" if the check box is selected
450 throw new NotImplementedException();
454 public override void DoDefaultAction ()
456 // change the state of the check box
459 public override int GetChildCount ()