PageRenderTime 41ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGridViewComboBoxCell.cs

https://bitbucket.org/danipen/mono
C# | 587 lines | 446 code | 97 blank | 44 comment | 84 complexity | b52c6d865dcfd3004e0f3c9cf66c18e8 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  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:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  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.
  19. //
  20. // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
  21. //
  22. // Author:
  23. // Pedro Martínez Juliá <pedromj@gmail.com>
  24. // Ivan N. Zlatev <contact@i-nz.net>
  25. //
  26. using System.Collections;
  27. using System.ComponentModel;
  28. using System.Drawing;
  29. namespace System.Windows.Forms {
  30. public class DataGridViewComboBoxCell : DataGridViewCell {
  31. private bool autoComplete;
  32. private object dataSource;
  33. private string displayMember;
  34. private DataGridViewComboBoxDisplayStyle displayStyle;
  35. private bool displayStyleForCurrentCellOnly;
  36. private int dropDownWidth;
  37. private FlatStyle flatStyle;
  38. private ObjectCollection items;
  39. private int maxDropDownItems;
  40. private bool sorted;
  41. private string valueMember;
  42. private DataGridViewComboBoxColumn owningColumnTemlate;
  43. public DataGridViewComboBoxCell () : base() {
  44. autoComplete = true;
  45. dataSource = null;
  46. displayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton;
  47. displayStyleForCurrentCellOnly = false;
  48. dropDownWidth = 1;
  49. flatStyle = FlatStyle.Standard;
  50. items = new ObjectCollection(this);
  51. maxDropDownItems = 8;
  52. sorted = false;
  53. owningColumnTemlate = null;
  54. }
  55. [DefaultValue (true)]
  56. public virtual bool AutoComplete {
  57. get { return autoComplete; }
  58. set { autoComplete = value; }
  59. }
  60. public virtual object DataSource {
  61. get { return dataSource; }
  62. set {
  63. if (value is IList || value is IListSource || value == null) {
  64. dataSource = value;
  65. return;
  66. }
  67. throw new Exception("Value is no IList, IListSource or null.");
  68. }
  69. }
  70. [DefaultValue ("")]
  71. public virtual string DisplayMember {
  72. get { return displayMember; }
  73. set { displayMember = value; }
  74. }
  75. [DefaultValue (DataGridViewComboBoxDisplayStyle.DropDownButton)]
  76. public DataGridViewComboBoxDisplayStyle DisplayStyle {
  77. get { return displayStyle; }
  78. set { displayStyle = value; }
  79. }
  80. [DefaultValue (false)]
  81. public bool DisplayStyleForCurrentCellOnly {
  82. get { return displayStyleForCurrentCellOnly; }
  83. set { displayStyleForCurrentCellOnly = value; }
  84. }
  85. [DefaultValue (1)]
  86. public virtual int DropDownWidth {
  87. get { return dropDownWidth; }
  88. set {
  89. if (value < 1) {
  90. throw new ArgumentOutOfRangeException("Value is less than 1.");
  91. }
  92. dropDownWidth = value;
  93. }
  94. }
  95. public override Type EditType {
  96. get { return typeof(DataGridViewComboBoxEditingControl); }
  97. }
  98. [DefaultValue (FlatStyle.Standard)]
  99. public FlatStyle FlatStyle {
  100. get { return flatStyle; }
  101. set {
  102. if (!Enum.IsDefined(typeof(FlatStyle), value)) {
  103. throw new InvalidEnumArgumentException("Value is not valid FlatStyle.");
  104. }
  105. flatStyle = value;
  106. }
  107. }
  108. public override Type FormattedValueType {
  109. get { return typeof(string); }
  110. }
  111. [Browsable (false)]
  112. public virtual ObjectCollection Items {
  113. get {
  114. if (DataGridView != null && DataGridView.BindingContext != null
  115. && DataSource != null && !String.IsNullOrEmpty (ValueMember)) {
  116. items.ClearInternal ();
  117. CurrencyManager dataManager = (CurrencyManager) DataGridView.BindingContext[DataSource];
  118. if (dataManager != null && dataManager.Count > 0) {
  119. foreach (object item in dataManager.List)
  120. items.AddInternal (item);
  121. }
  122. }
  123. return items;
  124. }
  125. }
  126. [DefaultValue (8)]
  127. public virtual int MaxDropDownItems {
  128. get { return maxDropDownItems; }
  129. set {
  130. if (value < 1 || value > 100) {
  131. throw new ArgumentOutOfRangeException("Value is less than 1 or greater than 100.");
  132. }
  133. maxDropDownItems = value;
  134. }
  135. }
  136. [DefaultValue (false)]
  137. public virtual bool Sorted {
  138. get { return sorted; }
  139. set {
  140. /*
  141. if () {
  142. throw new ArgumentException("Cannot sort a cell attached to a data source.");
  143. }
  144. */
  145. sorted = value;
  146. }
  147. }
  148. [DefaultValue ("")]
  149. public virtual string ValueMember {
  150. get { return valueMember; }
  151. set { valueMember = value; }
  152. }
  153. public override Type ValueType {
  154. get { return typeof(string); }
  155. }
  156. // Valid only for template Cells and used as a bridge to push items
  157. internal DataGridViewComboBoxColumn OwningColumnTemplate {
  158. get { return owningColumnTemlate; }
  159. set { owningColumnTemlate = value; }
  160. }
  161. public override object Clone () {
  162. DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell) base.Clone();
  163. cell.autoComplete = this.autoComplete;
  164. cell.dataSource = this.dataSource;
  165. cell.displayStyle = this.displayStyle;
  166. cell.displayMember = this.displayMember;
  167. cell.valueMember = this.valueMember;
  168. cell.displayStyleForCurrentCellOnly = this.displayStyleForCurrentCellOnly;
  169. cell.dropDownWidth = this.dropDownWidth;
  170. cell.flatStyle = this.flatStyle;
  171. cell.items.AddRangeInternal(this.items);
  172. cell.maxDropDownItems = this.maxDropDownItems;
  173. cell.sorted = this.sorted;
  174. return cell;
  175. }
  176. public override void DetachEditingControl () {
  177. this.DataGridView.EditingControlInternal = null;
  178. }
  179. public override void InitializeEditingControl (int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) {
  180. base.InitializeEditingControl (rowIndex, initialFormattedValue, dataGridViewCellStyle);
  181. ComboBox editingControl = DataGridView.EditingControl as ComboBox;
  182. editingControl.DropDownStyle = ComboBoxStyle.DropDownList;
  183. editingControl.Sorted = Sorted;
  184. editingControl.DataSource = null;
  185. editingControl.ValueMember = null;
  186. editingControl.DisplayMember = null;
  187. editingControl.Items.Clear();
  188. editingControl.SelectedIndex = -1;
  189. if (DataSource != null) {
  190. editingControl.DataSource = DataSource;
  191. editingControl.ValueMember = ValueMember;
  192. editingControl.DisplayMember = DisplayMember;
  193. } else {
  194. editingControl.Items.AddRange (this.Items);
  195. if (initialFormattedValue != null && editingControl.Items.IndexOf (initialFormattedValue) != -1)
  196. editingControl.SelectedItem = initialFormattedValue;
  197. }
  198. }
  199. internal void SyncItems ()
  200. {
  201. if (DataSource != null || OwningColumnTemplate == null)
  202. return;
  203. if (OwningColumnTemplate.DataGridView != null) {
  204. DataGridViewComboBoxEditingControl editor = OwningColumnTemplate.DataGridView.EditingControl
  205. as DataGridViewComboBoxEditingControl;
  206. if (editor != null) {
  207. object selectedItem = editor.SelectedItem;
  208. editor.Items.Clear ();
  209. editor.Items.AddRange (items);
  210. if (editor.Items.IndexOf (selectedItem) != -1)
  211. editor.SelectedItem = selectedItem;
  212. }
  213. }
  214. // Push the new items to the column
  215. OwningColumnTemplate.SyncItems (Items);
  216. }
  217. public override bool KeyEntersEditMode (KeyEventArgs e)
  218. {
  219. if (e.KeyCode == Keys.Space)
  220. return true;
  221. if ((int)e.KeyCode >= 48 && (int)e.KeyCode <= 90)
  222. return true;
  223. if ((int)e.KeyCode >= 96 && (int)e.KeyCode <= 111)
  224. return true;
  225. if (e.KeyCode == Keys.BrowserSearch || e.KeyCode == Keys.SelectMedia)
  226. return true;
  227. if ((int)e.KeyCode >= 186 && (int)e.KeyCode <= 229)
  228. return true;
  229. if (e.KeyCode == Keys.Attn || e.KeyCode == Keys.Packet)
  230. return true;
  231. if ((int)e.KeyCode >= 248 && (int)e.KeyCode <= 254)
  232. return true;
  233. if (e.KeyCode == Keys.F4)
  234. return true;
  235. if ((e.Modifiers == Keys.Alt) && (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up))
  236. return true;
  237. return false;
  238. }
  239. public override object ParseFormattedValue (object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
  240. {
  241. return base.ParseFormattedValue (formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter);
  242. }
  243. public override string ToString () {
  244. return string.Format ("DataGridViewComboBoxCell {{ ColumnIndex={0}, RowIndex={1} }}", ColumnIndex, RowIndex);
  245. }
  246. protected override Rectangle GetContentBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
  247. {
  248. if (DataGridView == null)
  249. return Rectangle.Empty;
  250. object o = FormattedValue;
  251. Size s = Size.Empty;
  252. if (o != null)
  253. s = DataGridViewCell.MeasureTextSize (graphics, o.ToString (), cellStyle.Font, TextFormatFlags.Default);
  254. return new Rectangle (1, (OwningRow.Height - s.Height) / 2, s.Width - 3, s.Height);
  255. }
  256. protected override Rectangle GetErrorIconBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
  257. {
  258. if (DataGridView == null || string.IsNullOrEmpty (ErrorText))
  259. return Rectangle.Empty;
  260. Size error_icon = new Size (12, 11);
  261. return new Rectangle (new Point (Size.Width - error_icon.Width - 23, (Size.Height - error_icon.Height) / 2), error_icon);
  262. }
  263. protected override object GetFormattedValue (object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
  264. {
  265. return base.GetFormattedValue (value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
  266. }
  267. protected override Size GetPreferredSize (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize)
  268. {
  269. object o = FormattedValue;
  270. if (o != null) {
  271. Size s = DataGridViewCell.MeasureTextSize (graphics, o.ToString (), cellStyle.Font, TextFormatFlags.Default);
  272. s.Height = Math.Max (s.Height, 22);
  273. s.Width += 25;
  274. return s;
  275. } else
  276. return new Size (39, 22);
  277. }
  278. protected override void OnDataGridViewChanged () {
  279. // Here we're supposed to do something with DataSource, etc, according to MSDN.
  280. base.OnDataGridViewChanged ();
  281. }
  282. protected override void OnEnter (int rowIndex, bool throughMouseClick) {
  283. base.OnEnter (rowIndex, throughMouseClick);
  284. }
  285. protected override void OnLeave (int rowIndex, bool throughMouseClick) {
  286. base.OnLeave (rowIndex, throughMouseClick);
  287. }
  288. protected override void OnMouseDown (DataGridViewCellMouseEventArgs e) {
  289. base.OnMouseDown (e);
  290. if (!ReadOnly)
  291. {
  292. // Any mouse-click on the cell should be passed along to any
  293. // combo-box control.
  294. if (IsInEditMode)
  295. {
  296. DataGridViewComboBoxEditingControl cb
  297. = (DataGridView.EditingControl
  298. as DataGridViewComboBoxEditingControl);
  299. if (cb != null)
  300. cb.OnMouseDownInternal (e);
  301. }
  302. }
  303. }
  304. protected override void OnMouseClick (DataGridViewCellMouseEventArgs e) {
  305. base.OnMouseClick (e);
  306. }
  307. protected override void OnMouseEnter (int rowIndex) {
  308. base.OnMouseEnter (rowIndex);
  309. }
  310. protected override void OnMouseLeave (int rowIndex) {
  311. base.OnMouseLeave (rowIndex);
  312. }
  313. protected override void OnMouseMove (DataGridViewCellMouseEventArgs e) {
  314. //Console.WriteLine ("MouseMove (Location: {0}", e.Location);
  315. base.OnMouseMove (e);
  316. }
  317. 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)
  318. {
  319. // The internal paint routines are overridden instead of
  320. // doing the custom paint logic here
  321. base.Paint (graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
  322. }
  323. internal override void PaintPartContent (Graphics graphics, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, object formattedValue)
  324. {
  325. Color color = Selected ? cellStyle.SelectionForeColor : cellStyle.ForeColor;
  326. TextFormatFlags flags = TextFormatFlags.EndEllipsis | TextFormatFlags.VerticalCenter | TextFormatFlags.TextBoxControl;
  327. Rectangle text_area = ContentBounds;
  328. text_area.X += cellBounds.X;
  329. text_area.Y += cellBounds.Y;
  330. Rectangle button_area = CalculateButtonArea (cellBounds);
  331. // The background of the dropdown button should be gray, not
  332. // the background color of the cell.
  333. graphics.FillRectangle (SystemBrushes.Control, button_area);
  334. ThemeEngine.Current.CPDrawComboButton (graphics, button_area, ButtonState.Normal);
  335. if (formattedValue != null)
  336. TextRenderer.DrawText (graphics, formattedValue.ToString (), cellStyle.Font, text_area, color, flags);
  337. }
  338. private Rectangle CalculateButtonArea (Rectangle cellBounds)
  339. {
  340. Rectangle button_area, text_area;
  341. int border = ThemeEngine.Current.Border3DSize.Width;
  342. const int button_width = 16;
  343. text_area = cellBounds;
  344. button_area = cellBounds;
  345. button_area.X = text_area.Right - button_width - border;
  346. button_area.Y = text_area.Y + border;
  347. button_area.Width = button_width;
  348. button_area.Height = text_area.Height - 2 * border;
  349. return button_area;
  350. }
  351. // IMPORTANT: Only call the internal methods from within DataGridViewComboBoxCell
  352. // for adding/removing/clearing because the other methods invoke an update of the
  353. // column items collection and you might end up in an endless loop.
  354. //
  355. [ListBindable (false)]
  356. public class ObjectCollection : IList, ICollection, IEnumerable {
  357. private ArrayList list;
  358. private DataGridViewComboBoxCell owner;
  359. public ObjectCollection (DataGridViewComboBoxCell owner)
  360. {
  361. this.owner = owner;
  362. list = new ArrayList();
  363. }
  364. public int Count {
  365. get { return list.Count; }
  366. }
  367. bool IList.IsFixedSize {
  368. get { return list.IsFixedSize; }
  369. }
  370. public bool IsReadOnly {
  371. get { return list.IsReadOnly; }
  372. }
  373. bool ICollection.IsSynchronized {
  374. get { return list.IsSynchronized; }
  375. }
  376. object ICollection.SyncRoot {
  377. get { return list.SyncRoot; }
  378. }
  379. public virtual object this [int index] {
  380. get { return list[index]; }
  381. set {
  382. ThrowIfOwnerIsDataBound ();
  383. list[index] = value;
  384. }
  385. }
  386. public int Add (object item)
  387. {
  388. ThrowIfOwnerIsDataBound ();
  389. int index = AddInternal (item);
  390. SyncOwnerItems ();
  391. return index;
  392. }
  393. internal int AddInternal (object item)
  394. {
  395. return list.Add (item);
  396. }
  397. internal void AddRangeInternal (ICollection items)
  398. {
  399. list.AddRange (items);
  400. }
  401. public void AddRange (ObjectCollection value)
  402. {
  403. ThrowIfOwnerIsDataBound ();
  404. AddRangeInternal (value);
  405. SyncOwnerItems ();
  406. }
  407. private void SyncOwnerItems ()
  408. {
  409. ThrowIfOwnerIsDataBound ();
  410. if (owner != null)
  411. owner.SyncItems ();
  412. }
  413. public void ThrowIfOwnerIsDataBound ()
  414. {
  415. if (owner != null && owner.DataGridView != null && owner.DataSource != null)
  416. throw new ArgumentException ("Cannot modify collection if the cell is data bound.");
  417. }
  418. public void AddRange (params object[] items)
  419. {
  420. ThrowIfOwnerIsDataBound ();
  421. AddRangeInternal (items);
  422. SyncOwnerItems ();
  423. }
  424. public void Clear ()
  425. {
  426. ThrowIfOwnerIsDataBound ();
  427. ClearInternal ();
  428. SyncOwnerItems ();
  429. }
  430. internal void ClearInternal ()
  431. {
  432. list.Clear ();
  433. }
  434. public bool Contains (object value)
  435. {
  436. return list.Contains(value);
  437. }
  438. void ICollection.CopyTo (Array destination, int index)
  439. {
  440. CopyTo ((object[]) destination, index);
  441. }
  442. public void CopyTo (object[] destination, int arrayIndex)
  443. {
  444. list.CopyTo (destination, arrayIndex);
  445. }
  446. public IEnumerator GetEnumerator ()
  447. {
  448. return list.GetEnumerator();
  449. }
  450. public int IndexOf (object value)
  451. {
  452. return list.IndexOf(value);
  453. }
  454. public void Insert (int index, object item)
  455. {
  456. ThrowIfOwnerIsDataBound ();
  457. InsertInternal (index, item);
  458. SyncOwnerItems ();
  459. }
  460. internal void InsertInternal (int index, object item)
  461. {
  462. list.Insert (index, item);
  463. }
  464. public void Remove (object value)
  465. {
  466. ThrowIfOwnerIsDataBound ();
  467. RemoveInternal (value);
  468. SyncOwnerItems ();
  469. }
  470. internal void RemoveInternal (object value)
  471. {
  472. list.Remove (value);
  473. }
  474. public void RemoveAt (int index)
  475. {
  476. ThrowIfOwnerIsDataBound ();
  477. RemoveAtInternal (index);
  478. SyncOwnerItems ();
  479. }
  480. internal void RemoveAtInternal (int index)
  481. {
  482. list.RemoveAt (index);
  483. }
  484. int IList.Add (object item)
  485. {
  486. return Add (item);
  487. }
  488. }
  489. }
  490. }