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>
29 using System
.Collections
;
30 using System
.ComponentModel
;
33 namespace System
.Windows
.Forms
{
35 public class DataGridViewComboBoxCell
: DataGridViewCell
{
37 private bool autoComplete
;
38 private object dataSource
;
39 private string displayMember
;
40 private DataGridViewComboBoxDisplayStyle displayStyle
;
41 private bool displayStyleForCurrentCellOnly
;
42 private int dropDownWidth
;
43 private FlatStyle flatStyle
;
44 private ObjectCollection items
;
45 private int maxDropDownItems
;
47 private string valueMember
;
49 private DataGridViewComboBoxEditingControl editingControl
;
51 public DataGridViewComboBoxCell () : base() {
54 displayStyle
= DataGridViewComboBoxDisplayStyle
.DropDownButton
;
55 displayStyleForCurrentCellOnly
= false;
57 flatStyle
= FlatStyle
.Standard
;
58 items
= new ObjectCollection(this);
64 public virtual bool AutoComplete
{
65 get { return autoComplete; }
66 set { autoComplete = value; }
69 public virtual object DataSource
{
70 get { return dataSource; }
72 if (value is IList
|| value is IListSource
|| value == null) {
76 throw new Exception("Value is no IList, IListSource or null.");
81 public virtual string DisplayMember
{
82 get { return displayMember; }
83 set { displayMember = value; }
86 [DefaultValue (DataGridViewComboBoxDisplayStyle
.DropDownButton
)]
87 public DataGridViewComboBoxDisplayStyle DisplayStyle
{
88 get { return displayStyle; }
89 set { displayStyle = value; }
92 [DefaultValue (false)]
93 public bool DisplayStyleForCurrentCellOnly
{
94 get { return displayStyleForCurrentCellOnly; }
95 set { displayStyleForCurrentCellOnly = value; }
99 public virtual int DropDownWidth
{
100 get { return dropDownWidth; }
103 throw new ArgumentOutOfRangeException("Value is less than 1.");
105 dropDownWidth
= value;
109 public override Type EditType
{
110 get { return typeof(DataGridViewComboBoxEditingControl); }
113 [DefaultValue (FlatStyle
.Standard
)]
114 public FlatStyle FlatStyle
{
115 get { return flatStyle; }
117 if (!Enum
.IsDefined(typeof(FlatStyle
), value)) {
118 throw new InvalidEnumArgumentException("Value is not valid FlatStyle.");
124 public override Type FormattedValueType
{
125 get { return typeof(string); }
129 public virtual ObjectCollection Items
{
130 get { return items; }
134 public virtual int MaxDropDownItems
{
135 get { return maxDropDownItems; }
137 if (value < 1 || value > 100) {
138 throw new ArgumentOutOfRangeException("Value is less than 1 or greater than 100.");
140 maxDropDownItems
= value;
144 [DefaultValue (false)]
145 public virtual bool Sorted
{
146 get { return sorted; }
150 throw new ArgumentException("Cannot sort a cell attached to a data source.");
158 public virtual string ValueMember
{
159 get { return valueMember; }
160 set { valueMember = value; }
163 public override Type ValueType
{
164 get { return typeof(string); }
167 public override object Clone () {
168 DataGridViewComboBoxCell cell
= (DataGridViewComboBoxCell
) base.Clone();
169 cell
.autoComplete
= this.autoComplete
;
170 cell
.dataSource
= this.dataSource
;
171 cell
.displayStyle
= this.displayStyle
;
172 cell
.displayStyleForCurrentCellOnly
= this.displayStyleForCurrentCellOnly
;
173 cell
.dropDownWidth
= this.dropDownWidth
;
174 cell
.flatStyle
= this.flatStyle
;
175 cell
.items
.AddRange(this.items
);
176 cell
.maxDropDownItems
= this.maxDropDownItems
;
177 cell
.sorted
= this.sorted
;
181 public override void DetachEditingControl () {
182 this.DataGridView
.EditingControlInternal
= null;
185 public override void InitializeEditingControl (int rowIndex
, object initialFormattedValue
, DataGridViewCellStyle dataGridViewCellStyle
) {
186 base.InitializeEditingControl (rowIndex
, initialFormattedValue
, dataGridViewCellStyle
);
188 editingControl
= DataGridView
.EditingControl
as DataGridViewComboBoxEditingControl
;
190 if (editingControl
== null)
193 string text
= initialFormattedValue
== null ? string.Empty
: initialFormattedValue
.ToString ();
195 // A simple way to check if the control has
196 // been initialized already.
197 if (editingControl
.Items
.Count
> 0) {
198 editingControl
.SelectedIndex
= editingControl
.FindString (text
);
202 editingControl
.DropDownStyle
= ComboBoxStyle
.DropDownList
;
203 editingControl
.Items
.AddRange (this.Items
);
205 editingControl
.Sorted
= sorted
;
206 editingControl
.SelectedIndex
= editingControl
.FindString (text
);
208 editingControl
.SelectedIndexChanged
+= new EventHandler (editingControl_SelectedIndexChanged
);
211 void editingControl_SelectedIndexChanged (object sender
, EventArgs e
)
213 Value
= editingControl
.SelectedItem
;
216 public override bool KeyEntersEditMode (KeyEventArgs e
)
218 if (e
.KeyCode
== Keys
.Space
)
220 if ((int)e
.KeyCode
>= 48 && (int)e
.KeyCode
<= 90)
222 if ((int)e
.KeyCode
>= 96 && (int)e
.KeyCode
<= 111)
224 if (e
.KeyCode
== Keys
.BrowserSearch
|| e
.KeyCode
== Keys
.SelectMedia
)
226 if ((int)e
.KeyCode
>= 186 && (int)e
.KeyCode
<= 229)
228 if (e
.KeyCode
== Keys
.Attn
|| e
.KeyCode
== Keys
.Packet
)
230 if ((int)e
.KeyCode
>= 248 && (int)e
.KeyCode
<= 254)
232 if (e
.KeyCode
== Keys
.F4
)
234 if ((e
.Modifiers
== Keys
.Alt
) && (e
.KeyCode
== Keys
.Down
|| e
.KeyCode
== Keys
.Up
))
240 public override object ParseFormattedValue (object formattedValue
, DataGridViewCellStyle cellStyle
, TypeConverter formattedValueTypeConverter
, TypeConverter valueTypeConverter
)
242 return base.ParseFormattedValue (formattedValue
, cellStyle
, formattedValueTypeConverter
, valueTypeConverter
);
245 public override string ToString () {
246 return string.Format ("DataGridViewComboBoxCell {{ ColumnIndex={0}, RowIndex={1} }}", ColumnIndex
, RowIndex
);
249 protected override Rectangle
GetContentBounds (Graphics graphics
, DataGridViewCellStyle cellStyle
, int rowIndex
)
251 if (DataGridView
== null)
252 return Rectangle
.Empty
;
254 object o
= FormattedValue
;
258 s
= DataGridViewCell
.MeasureTextSize (graphics
, o
.ToString (), cellStyle
.Font
, TextFormatFlags
.Default
);
260 return new Rectangle (1, (OwningRow
.Height
- s
.Height
) / 2, s
.Width
- 3, s
.Height
);
263 protected override Rectangle
GetErrorIconBounds (Graphics graphics
, DataGridViewCellStyle cellStyle
, int rowIndex
)
265 if (DataGridView
== null || string.IsNullOrEmpty (ErrorText
))
266 return Rectangle
.Empty
;
268 Size error_icon
= new Size (12, 11);
269 return new Rectangle (new Point (Size
.Width
- error_icon
.Width
- 23, (Size
.Height
- error_icon
.Height
) / 2), error_icon
);
272 protected override object GetFormattedValue (object value, int rowIndex
, ref DataGridViewCellStyle cellStyle
, TypeConverter valueTypeConverter
, TypeConverter formattedValueTypeConverter
, DataGridViewDataErrorContexts context
)
274 return base.GetFormattedValue (value, rowIndex
, ref cellStyle
, valueTypeConverter
, formattedValueTypeConverter
, context
);
277 protected override Size
GetPreferredSize (Graphics graphics
, DataGridViewCellStyle cellStyle
, int rowIndex
, Size constraintSize
)
279 object o
= FormattedValue
;
282 Size s
= DataGridViewCell
.MeasureTextSize (graphics
, o
.ToString (), cellStyle
.Font
, TextFormatFlags
.Default
);
283 s
.Height
= Math
.Max (s
.Height
, 22);
287 return new Size (39, 22);
290 protected override void OnDataGridViewChanged () {
291 // Here we're supposed to do something with DataSource, etc, according to MSDN.
292 base.OnDataGridViewChanged ();
295 protected override void OnEnter (int rowIndex
, bool throughMouseClick
) {
296 base.OnEnter (rowIndex
, throughMouseClick
);
299 protected override void OnLeave (int rowIndex
, bool throughMouseClick
) {
300 base.OnLeave (rowIndex
, throughMouseClick
);
303 protected override void OnMouseClick (DataGridViewCellMouseEventArgs e
) {
304 base.OnMouseClick (e
);
307 protected override void OnMouseEnter (int rowIndex
) {
308 base.OnMouseEnter (rowIndex
);
311 protected override void OnMouseLeave (int rowIndex
) {
312 base.OnMouseLeave (rowIndex
);
315 protected override void OnMouseMove (DataGridViewCellMouseEventArgs e
) {
316 //Console.WriteLine ("MouseMove (Location: {0}", e.Location);
317 base.OnMouseMove (e
);
320 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
)
322 // The internal paint routines are overridden instead of
323 // doing the custom paint logic here
324 base.Paint (graphics
, clipBounds
, cellBounds
, rowIndex
, elementState
, value, formattedValue
, errorText
, cellStyle
, advancedBorderStyle
, paintParts
);
327 internal override void PaintPartContent (Graphics graphics
, Rectangle cellBounds
, int rowIndex
, DataGridViewElementStates cellState
, DataGridViewCellStyle cellStyle
, object formattedValue
)
329 Color color
= Selected
? cellStyle
.SelectionForeColor
: cellStyle
.ForeColor
;
330 TextFormatFlags flags
= TextFormatFlags
.EndEllipsis
| TextFormatFlags
.VerticalCenter
| TextFormatFlags
.TextBoxControl
;
332 Rectangle text_area
= ContentBounds
;
333 text_area
.X
+= cellBounds
.X
;
334 text_area
.Y
+= cellBounds
.Y
;
336 Rectangle button_area
= CalculateButtonArea (cellBounds
);
338 // The background of the dropdown button should be gray, not
339 // the background color of the cell.
340 graphics
.FillRectangle (SystemBrushes
.Control
, button_area
);
341 ThemeEngine
.Current
.CPDrawComboButton (graphics
, button_area
, ButtonState
.Normal
);
343 if (formattedValue
!= null)
344 TextRenderer
.DrawText (graphics
, formattedValue
.ToString (), cellStyle
.Font
, text_area
, color
, flags
);
347 private Rectangle
CalculateButtonArea (Rectangle cellBounds
)
349 Rectangle button_area
, text_area
;
350 int border
= ThemeEngine
.Current
.Border3DSize
.Width
;
351 const int button_width
= 16;
353 text_area
= cellBounds
;
355 button_area
= cellBounds
;
356 button_area
.X
= text_area
.Right
- button_width
- border
;
357 button_area
.Y
= text_area
.Y
+ border
;
358 button_area
.Width
= button_width
;
359 button_area
.Height
= text_area
.Height
- 2 * border
;
364 [ListBindable (false)]
365 public class ObjectCollection
: IList
, ICollection
, IEnumerable
{
367 private ArrayList list
;
369 //private DataGridViewComboBoxCell owner;
371 public ObjectCollection (DataGridViewComboBoxCell owner
) {
372 //this.owner = owner;
373 list
= new ArrayList();
377 get { return list.Count; }
380 bool IList
.IsFixedSize
{
381 get { return list.IsFixedSize; }
384 public bool IsReadOnly
{
385 get { return list.IsReadOnly; }
388 bool ICollection
.IsSynchronized
{
389 get { return list.IsSynchronized; }
392 object ICollection
.SyncRoot
{
393 get { return list.SyncRoot; }
396 public virtual object this [int index
] {
397 get { return list[index]; }
398 set { list[index] = value; }
401 public int Add (object item
) {
402 return list
.Add(item
);
405 public void AddRange (ObjectCollection
value) {
406 list
.AddRange(value.list
);
409 public void AddRange (params object[] items
) {
410 list
.AddRange(items
);
413 public void Clear () {
417 public bool Contains (object value) {
418 return list
.Contains(value);
421 void ICollection
.CopyTo (Array destination
, int index
)
423 CopyTo ((object[]) destination
, index
);
426 public void CopyTo (object[] destination
, int arrayIndex
)
428 list
.CopyTo (destination
, arrayIndex
);
431 public IEnumerator
GetEnumerator () {
432 return list
.GetEnumerator();
435 public int IndexOf (object value) {
436 return list
.IndexOf(value);
439 public void Insert (int index
, object item
) {
440 list
.Insert(index
, item
);
443 public void Remove (object value) {
447 public void RemoveAt (int index
) {
448 list
.RemoveAt(index
);
452 int IList
.Add (object item
)