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)
291 DataGridView.BeginEdit (false);
293 CheckState cs = GetCurrentValue ();
296 if (cs == CheckState.Indeterminate)
297 editingCellFormattedValue = CheckState.Unchecked;
298 else if (cs == CheckState.Checked)
299 editingCellFormattedValue = CheckState.Indeterminate;
301 editingCellFormattedValue = CheckState.Checked;
303 if (cs == CheckState.Checked)
304 editingCellFormattedValue = false;
306 editingCellFormattedValue = true;
309 editingCellValueChanged = true;
312 protected override void OnContentDoubleClick (DataGridViewCellEventArgs e)
316 protected override void OnKeyDown (KeyEventArgs e, int rowIndex)
318 // when activated by the SPACE key, this method updates the cell's user interface
319 if ((e.KeyData & Keys.Space) == Keys.Space) {
320 check_state = PushButtonState.Pressed;
321 DataGridView.InvalidateCell (this);
325 protected override void OnKeyUp (KeyEventArgs e, int rowIndex)
327 // when activated by the SPACE key, this method updates the cell's user interface
328 if ((e.KeyData & Keys.Space) == Keys.Space) {
329 check_state = PushButtonState.Normal;
330 DataGridView.InvalidateCell (this);
334 protected override void OnLeave (int rowIndex, bool throughMouseClick)
336 if (check_state != PushButtonState.Normal) {
337 check_state = PushButtonState.Normal;
338 DataGridView.InvalidateCell (this);
342 protected override void OnMouseDown (DataGridViewCellMouseEventArgs e)
344 // if activated by depresing the left mouse button, this method updates the cell's user interface
345 if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
346 check_state = PushButtonState.Pressed;
347 DataGridView.InvalidateCell (this);
351 protected override void OnMouseLeave (int rowIndex)
353 // if the cell's button is not in its normal state, this method causes the cell's user interface to be updated.
354 if (check_state != PushButtonState.Normal) {
355 check_state = PushButtonState.Normal;
356 DataGridView.InvalidateCell (this);
360 protected override void OnMouseMove (DataGridViewCellMouseEventArgs e)
362 if (check_state != PushButtonState.Normal && check_state != PushButtonState.Hot) {
363 check_state = PushButtonState.Hot;
364 DataGridView.InvalidateCell (this);
368 protected override void OnMouseUp (DataGridViewCellMouseEventArgs e)
370 // if activated by the left mouse button, this method updates the cell's user interface
371 if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
372 check_state = PushButtonState.Normal;
373 DataGridView.InvalidateCell (this);
377 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)
379 base.Paint (graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
382 internal override void PaintPartContent (Graphics graphics, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, object formattedValue)
385 CheckState value = GetCurrentValue ();
387 if ((CheckState)value == CheckState.Unchecked)
388 state = (CheckBoxState)check_state;
389 else if ((CheckState)value == CheckState.Checked)
390 state = (CheckBoxState)((int)check_state + 4);
392 state = (CheckBoxState)((int)check_state + 8);
394 state = (CheckBoxState)check_state;
396 Point p = new Point (cellBounds.X + (Size.Width - 13) / 2, cellBounds.Y + (Size.Height - 13) / 2);
397 CheckBoxRenderer.DrawCheckBox (graphics, p, state);
400 private CheckState GetCurrentValue ()
402 CheckState cs = CheckState.Indeterminate;
406 if (editingCellValueChanged)
407 current_obj = editingCellFormattedValue;
411 if (current_obj == null)
412 cs = CheckState.Indeterminate;
413 else if (current_obj is bool)
415 if ((bool)current_obj == true)
416 cs = CheckState.Checked;
417 else if ((bool)current_obj == false)
418 cs = CheckState.Unchecked;
420 else if (current_obj is CheckState)
421 cs = (CheckState)current_obj;
426 protected class DataGridViewCheckBoxCellAccessibleObject : DataGridViewCellAccessibleObject {
428 public DataGridViewCheckBoxCellAccessibleObject (DataGridViewCell owner) : base(owner)
432 public override string DefaultAction {
434 if (Owner.ReadOnly) {
437 // return "Press to check" if the check box is not selected
438 // and "Press to uncheck" if the check box is selected
439 throw new NotImplementedException();
443 public override void DoDefaultAction ()
445 // change the state of the check box
448 public override int GetChildCount ()