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>
28 using System.ComponentModel;
30 using System.Windows.Forms.VisualStyles;
32 namespace System.Windows.Forms {
34 public class DataGridViewCheckBoxCell : DataGridViewCell, IDataGridViewEditingCell {
36 private object editingCellFormattedValue;
37 private bool editingCellValueChanged;
38 private object falseValue;
39 private FlatStyle flatStyle;
40 private object indeterminateValue;
41 private bool threeState;
42 private object trueValue;
43 // private Type valueType;
44 private PushButtonState check_state;
46 public DataGridViewCheckBoxCell ()
48 check_state = PushButtonState.Normal;
49 editingCellFormattedValue = false;
50 editingCellValueChanged = false;
52 flatStyle = FlatStyle.Standard;
53 indeterminateValue = null;
59 public DataGridViewCheckBoxCell (bool threeState) : this()
61 this.threeState = threeState;
62 editingCellFormattedValue = CheckState.Unchecked;
65 public virtual object EditingCellFormattedValue {
66 get { return editingCellFormattedValue; }
68 if (FormattedValueType == null || value == null || value.GetType() != FormattedValueType || !(value is Boolean) || !(value is CheckState)) {
69 throw new ArgumentException("Cannot set this property.");
71 editingCellFormattedValue = value;
75 public virtual bool EditingCellValueChanged {
76 get { return editingCellValueChanged; }
77 set { editingCellValueChanged = value; }
80 public override Type EditType {
85 public object FalseValue {
86 get { return falseValue; }
87 set { falseValue = value; }
90 [DefaultValue (FlatStyle.Standard)]
91 public FlatStyle FlatStyle {
92 get { return flatStyle; }
94 if (!Enum.IsDefined(typeof(FlatStyle), value)) {
95 throw new InvalidEnumArgumentException("Value is not valid FlatStyle.");
97 if (value == FlatStyle.Popup) {
98 throw new Exception("FlatStyle cannot be set to Popup in this control.");
103 public override Type FormattedValueType {
106 return typeof(CheckState);
108 return typeof(Boolean);
112 [DefaultValue (null)]
113 public object IndeterminateValue {
114 get { return indeterminateValue; }
115 set { indeterminateValue = value; }
118 [DefaultValue (false)]
119 public bool ThreeState {
120 get { return threeState; }
121 set { threeState = value; }
124 [DefaultValue (null)]
125 public object TrueValue {
126 get { return trueValue; }
127 set { trueValue = value; }
130 public override Type ValueType {
132 if (base.ValueType == null) {
133 if (OwningColumn != null && OwningColumn.ValueType != null) {
134 return OwningColumn.ValueType;
137 return typeof(CheckState);
139 return typeof(Boolean);
141 return base.ValueType;
143 set { base.ValueType = value; }
146 public override object Clone ()
148 DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell) base.Clone();
149 cell.editingCellValueChanged = this.editingCellValueChanged;
150 cell.editingCellFormattedValue = this.editingCellFormattedValue;
151 cell.falseValue = this.falseValue;
152 cell.flatStyle = this.flatStyle;
153 cell.indeterminateValue = this.indeterminateValue;
154 cell.threeState = this.threeState;
155 cell.trueValue = this.trueValue;
156 cell.ValueType = this.ValueType;
160 public virtual object GetEditingCellFormattedValue (DataGridViewDataErrorContexts context)
162 if (FormattedValueType == null) {
163 throw new InvalidOperationException("FormattedValueType is null.");
165 if ((context & DataGridViewDataErrorContexts.ClipboardContent) != 0) {
166 return Convert.ToString(Value);
169 if (editingCellFormattedValue == null)
171 return CheckState.Indeterminate;
175 return editingCellFormattedValue;
178 public override object ParseFormattedValue (object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
180 if (cellStyle == null) {
181 throw new ArgumentNullException("CellStyle is null");
183 if (FormattedValueType == null) {
184 throw new FormatException("FormattedValueType is null.");
186 if (formattedValue == null || formattedValue.GetType() != FormattedValueType) {
187 throw new ArgumentException("FormattedValue is null or is not instance of FormattedValueType.");
190 return base.ParseFormattedValue (formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter);
193 public virtual void PrepareEditingCellForEdit (bool selectAll)
195 editingCellFormattedValue = GetCurrentValue ();
198 public override string ToString ()
200 return string.Format ("DataGridViewCheckBoxCell {{ ColumnIndex={0}, RowIndex={1} }}", ColumnIndex, RowIndex);
203 protected override bool ContentClickUnsharesRow (DataGridViewCellEventArgs e)
205 return this.IsInEditMode;
208 protected override bool ContentDoubleClickUnsharesRow (DataGridViewCellEventArgs e)
210 return this.IsInEditMode;
213 protected override AccessibleObject CreateAccessibilityInstance ()
215 return new DataGridViewCheckBoxCellAccessibleObject(this);
218 protected override Rectangle GetContentBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
220 if (DataGridView == null)
221 return Rectangle.Empty;
223 return new Rectangle ((Size.Width - 13) / 2, (Size.Height - 13) / 2, 13, 13);
226 protected override Rectangle GetErrorIconBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
228 if (DataGridView == null || string.IsNullOrEmpty (ErrorText))
229 return Rectangle.Empty;
231 Size error_icon = new Size (12, 11);
232 return new Rectangle (new Point (Size.Width - error_icon.Width - 5, (Size.Height - error_icon.Height) / 2), error_icon);
235 protected override object GetFormattedValue (object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
237 if (DataGridView == null || value == null)
239 return CheckState.Indeterminate;
246 protected override Size GetPreferredSize (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize)
248 return new Size (21, 20);
251 protected override bool KeyDownUnsharesRow (KeyEventArgs e, int rowIndex)
253 // true if the user pressed the SPACE key without modifier keys; otherwise, false
254 return e.KeyData == Keys.Space;
257 protected override bool KeyUpUnsharesRow (KeyEventArgs e, int rowIndex)
259 // true if the user released the SPACE key; otherwise false
260 return e.KeyData == Keys.Space;
263 protected override bool MouseDownUnsharesRow (DataGridViewCellMouseEventArgs e)
265 return (e.Button == MouseButtons.Left);
268 protected override bool MouseEnterUnsharesRow (int rowIndex)
270 // true if the cell was the last cell receiving a mouse click; otherwise, false.
274 protected override bool MouseLeaveUnsharesRow (int rowIndex)
276 // true if the button displayed by the cell is in the pressed state; otherwise, false.
277 return check_state == PushButtonState.Pressed;
280 protected override bool MouseUpUnsharesRow (DataGridViewCellMouseEventArgs e)
282 // true if the mouse up was caused by the release of the left mouse button; otherwise false.
283 return e.Button == MouseButtons.Left;
286 protected override void OnContentClick (DataGridViewCellEventArgs e)
292 DataGridView.BeginEdit (false);
297 private void ToggleCheckState ()
299 CheckState cs = GetCurrentValue ();
302 if (cs == CheckState.Indeterminate)
303 editingCellFormattedValue = CheckState.Unchecked;
304 else if (cs == CheckState.Checked)
305 editingCellFormattedValue = CheckState.Indeterminate;
307 editingCellFormattedValue = CheckState.Checked;
309 if (cs == CheckState.Checked)
310 editingCellFormattedValue = false;
312 editingCellFormattedValue = true;
315 editingCellValueChanged = true;
316 DataGridView.InvalidateCell (this);
319 protected override void OnContentDoubleClick (DataGridViewCellEventArgs e)
323 protected override void OnKeyDown (KeyEventArgs e, int rowIndex)
325 // when activated by the SPACE key, this method updates the cell's user interface
326 if (!ReadOnly && (e.KeyData & Keys.Space) == Keys.Space) {
327 check_state = PushButtonState.Pressed;
328 DataGridView.InvalidateCell (this);
332 protected override void OnKeyUp (KeyEventArgs e, int rowIndex)
334 // when activated by the SPACE key, this method updates the cell's user interface
335 if (!ReadOnly && (e.KeyData & Keys.Space) == Keys.Space) {
336 check_state = PushButtonState.Normal;
338 DataGridView.BeginEdit (false);
343 protected override void OnLeave (int rowIndex, bool throughMouseClick)
345 if (!ReadOnly && check_state != PushButtonState.Normal) {
346 check_state = PushButtonState.Normal;
347 DataGridView.InvalidateCell (this);
351 protected override void OnMouseDown (DataGridViewCellMouseEventArgs e)
353 // if activated by depresing the left mouse button, this method updates the cell's user interface
354 if (!ReadOnly && (e.Button & MouseButtons.Left) == MouseButtons.Left) {
355 check_state = PushButtonState.Pressed;
356 DataGridView.InvalidateCell (this);
360 protected override void OnMouseLeave (int rowIndex)
362 // if the cell's button is not in its normal state, this method causes the cell's user interface to be updated.
363 if (!ReadOnly && check_state != PushButtonState.Normal) {
364 check_state = PushButtonState.Normal;
365 DataGridView.InvalidateCell (this);
369 protected override void OnMouseMove (DataGridViewCellMouseEventArgs e)
371 if (!ReadOnly && check_state != PushButtonState.Normal && check_state != PushButtonState.Hot) {
372 check_state = PushButtonState.Hot;
373 DataGridView.InvalidateCell (this);
377 protected override void OnMouseUp (DataGridViewCellMouseEventArgs e)
379 // if activated by the left mouse button, this method updates the cell's user interface
380 if (!ReadOnly && (e.Button & MouseButtons.Left) == MouseButtons.Left) {
381 check_state = PushButtonState.Normal;
382 DataGridView.InvalidateCell (this);
386 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)
388 base.Paint (graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
391 internal override void PaintPartContent (Graphics graphics, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, object formattedValue)
394 CheckState value = GetCurrentValue ();
396 if ((CheckState)value == CheckState.Unchecked)
397 state = (CheckBoxState)check_state;
398 else if ((CheckState)value == CheckState.Checked)
399 state = (CheckBoxState)((int)check_state + 4);
401 state = (CheckBoxState)((int)check_state + 8);
403 state = (CheckBoxState)check_state;
405 Point p = new Point (cellBounds.X + (Size.Width - 13) / 2, cellBounds.Y + (Size.Height - 13) / 2);
406 CheckBoxRenderer.DrawCheckBox (graphics, p, state);
409 private CheckState GetCurrentValue ()
411 CheckState cs = CheckState.Indeterminate;
415 if (editingCellValueChanged)
416 current_obj = editingCellFormattedValue;
420 if (current_obj == null)
421 cs = CheckState.Indeterminate;
422 else if (current_obj is bool)
424 if ((bool)current_obj == true)
425 cs = CheckState.Checked;
426 else if ((bool)current_obj == false)
427 cs = CheckState.Unchecked;
429 else if (current_obj is CheckState)
430 cs = (CheckState)current_obj;
435 protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject {
437 public DataGridViewCheckBoxCellAccessibleObject (DataGridViewCell owner) : base(owner)
441 public override string DefaultAction {
443 if (Owner.ReadOnly) {
446 // return "Press to check" if the check box is not selected
447 // and "Press to uncheck" if the check box is selected
448 throw new NotImplementedException();
452 public override void DoDefaultAction ()
454 // change the state of the check box
457 public override int GetChildCount ()