Fix bug #395
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListViewItem.cs
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) 2004 Novell, Inc. (http://www.novell.com)
21 //
22 // Author:
23 //      Ravindra (rkumar@novell.com)
24 //      Mike Kestner <mkestner@novell.com>
25 //      Daniel Nauck (dna(at)mono-project(dot)de)
26
27 using System.Collections;
28 using System.ComponentModel;
29 using System.Drawing;
30 using System.Runtime.Serialization;
31
32 namespace System.Windows.Forms
33 {
34         [DefaultProperty ("Text")]
35         [DesignTimeVisible (false)]
36         [Serializable]
37         [ToolboxItem (false)]
38         [TypeConverter (typeof (ListViewItemConverter))]
39         public class ListViewItem : ICloneable, ISerializable
40         {
41                 #region Instance Variables
42                 private int image_index = -1;
43                 private bool is_checked = false;
44                 private int state_image_index = -1;
45                 private ListViewSubItemCollection sub_items;
46                 private object tag;
47                 private bool use_item_style = true;
48                 int display_index = -1;                 // actual position in ListView
49                 private ListViewGroup group = null;
50                 private string name = String.Empty;
51                 private string image_key = String.Empty;
52                 string tooltip_text = String.Empty;
53                 int indent_count;
54                 Point position = new Point (-1, -1);            // cached to mimic .Net behaviour       
55                 Rectangle bounds = Rectangle.Empty;
56                 Rectangle checkbox_rect;        // calculated by CalcListViewItem method
57                 Rectangle icon_rect;
58                 Rectangle item_rect;
59                 Rectangle label_rect;
60                 ListView owner;
61                 Font font;
62                 Font hot_font;                  // cached font for hot tracking
63                 bool selected;
64
65                 internal int row;
66                 internal int col;
67
68         
69                 #region UIA Framework: Methods, Properties and Events
70
71                 internal event EventHandler UIATextChanged;
72         
73                 internal event LabelEditEventHandler UIASubItemTextChanged;
74
75                 internal void OnUIATextChanged ()
76                 {
77                         if (UIATextChanged != null)
78                                 UIATextChanged (this, EventArgs.Empty);
79                 }
80
81                 internal void OnUIASubItemTextChanged (LabelEditEventArgs args)
82                 {
83                         //If our index is 0 we also generate TextChanged for the ListViewItem
84                         //because ListViewItem.Text is the same as ListViewItem.SubItems [0].Text
85                         if (args.Item == 0)
86                                 OnUIATextChanged ();
87
88                         if (UIASubItemTextChanged != null)
89                                 UIASubItemTextChanged (this, args);
90                 }
91
92                 #endregion // UIA Framework: Methods, Properties and Events
93
94
95                 #endregion Instance Variables
96
97                 #region Public Constructors
98                 public ListViewItem () : this (string.Empty)
99                 {
100                 }
101
102                 public ListViewItem (string text) : this (text, -1)
103                 {
104                 }
105
106                 public ListViewItem (string [] items) : this (items, -1)
107                 {
108                 }
109
110                 public ListViewItem (ListViewItem.ListViewSubItem [] subItems, int imageIndex)
111                 {
112                         this.sub_items = new ListViewSubItemCollection (this, null);
113                         for (int i = 0; i < subItems.Length; i++)
114                                 sub_items.Add (subItems [i]);
115                         this.image_index = imageIndex;
116                 }
117
118                 public ListViewItem (string text, int imageIndex)
119                 {
120                         this.image_index = imageIndex;
121                         this.sub_items = new ListViewSubItemCollection (this, text);
122                 }
123
124                 public ListViewItem (string [] items, int imageIndex)
125                 {
126                         this.sub_items = new ListViewSubItemCollection (this, null);
127                         if (items != null) {
128                                 for (int i = 0; i < items.Length; i++)
129                                         sub_items.Add (new ListViewSubItem (this, items [i]));
130                         }
131                         this.image_index = imageIndex;
132                 }
133
134                 public ListViewItem (string [] items, int imageIndex, Color foreColor, 
135                                      Color backColor, Font font) : this (items, imageIndex)
136                 {
137                         ForeColor = foreColor;
138                         BackColor = backColor;
139                         this.font = font;
140                 }
141
142                 public ListViewItem(string[] items, string imageKey) : this(items)
143                 {
144                         this.ImageKey = imageKey;
145                 }
146
147                 public ListViewItem(string text, string imageKey) : this(text)
148                 {
149                         this.ImageKey = imageKey;
150                 }
151
152                 public ListViewItem(ListViewSubItem[] subItems, string imageKey)
153                 {
154                         this.sub_items = new ListViewSubItemCollection (this, null);
155                         for (int i = 0; i < subItems.Length; i++)
156                                 this.sub_items.Add (subItems [i]);
157                         this.ImageKey = imageKey;
158                 }
159
160                 public ListViewItem(string[] items, string imageKey, Color foreColor,
161                                         Color backColor, Font font) : this(items, imageKey)
162                 {
163                         ForeColor = foreColor;
164                         BackColor = backColor;
165                         this.font = font;
166                 }
167
168                 public ListViewItem(ListViewGroup group) : this()
169                 {
170                         Group = group;
171                 }
172
173                 public ListViewItem(string text, ListViewGroup group) : this(text)
174                 {
175                         Group = group;
176                 }
177
178                 public ListViewItem(string[] items, ListViewGroup group) : this(items)
179                 {
180                         Group = group;
181                 }
182
183                 public ListViewItem(ListViewSubItem[] subItems, int imageIndex, ListViewGroup group)
184                         : this(subItems, imageIndex)
185                 {
186                         Group = group;
187                 }
188
189                 public ListViewItem(ListViewSubItem[] subItems, string imageKey, ListViewGroup group)
190                         : this(subItems, imageKey)
191                 {
192                         Group = group;
193                 }
194
195                 public ListViewItem(string text, int imageIndex, ListViewGroup group)
196                         : this(text, imageIndex)
197                 {
198                         Group = group;
199                 }
200
201                 public ListViewItem(string text, string imageKey, ListViewGroup group)
202                         : this(text, imageKey)
203                 {
204                         Group = group;
205                 }
206
207                 public ListViewItem(string[] items, int imageIndex, ListViewGroup group)
208                         : this(items, imageIndex)
209                 {
210                         Group = group;
211                 }
212
213                 public ListViewItem(string[] items, string imageKey, ListViewGroup group)
214                         : this(items, imageKey)
215                 {
216                         Group = group;
217                 }
218
219                 public ListViewItem(string[] items, int imageIndex, Color foreColor, Color backColor,
220                                 Font font, ListViewGroup group)
221                         : this(items, imageIndex, foreColor, backColor, font)
222                 {
223                         Group = group;
224                 }
225
226                 public ListViewItem(string[] items, string imageKey, Color foreColor, Color backColor,
227                                 Font font, ListViewGroup group)
228                         : this(items, imageKey, foreColor, backColor, font)
229                 {
230                         Group = group;
231                 }
232                 #endregion      // Public Constructors
233
234                 protected ListViewItem (SerializationInfo info, StreamingContext context)
235                 {
236                         Deserialize (info, context);
237                 }
238
239                 #region Public Instance Properties
240                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
241                 public Color BackColor {
242                         get {
243                                 if (sub_items.Count > 0)
244                                         return sub_items[0].BackColor;
245
246                                 if (owner != null)
247                                         return owner.BackColor;
248                                 
249                                 return ThemeEngine.Current.ColorWindow;
250                         }
251                         set { SubItems [0].BackColor = value; }
252                 }
253
254                 [Browsable (false)]
255                 public Rectangle Bounds {
256                         get {
257                                 return GetBounds (ItemBoundsPortion.Entire);
258                         }
259                 }
260
261                 [DefaultValue (false)]
262                 [RefreshProperties (RefreshProperties.Repaint)]
263                 public bool Checked {
264                         get { return is_checked; }
265                         set { 
266                                 if (is_checked == value)
267                                         return;
268                                 
269                                 if (owner != null) {
270                                         CheckState current_value = is_checked ? CheckState.Checked : CheckState.Unchecked;
271                                         CheckState new_value = value ? CheckState.Checked : CheckState.Unchecked;
272
273                                         ItemCheckEventArgs icea = new ItemCheckEventArgs (Index,
274                                                         new_value, current_value);
275                                         owner.OnItemCheck (icea);
276
277                                         if (new_value != current_value) {
278                                                 // force re-population of list
279                                                 owner.CheckedItems.Reset ();
280                                                 is_checked = new_value == CheckState.Checked;
281                                                 Invalidate ();
282
283                                                 ItemCheckedEventArgs args = new ItemCheckedEventArgs (this);
284                                                 owner.OnItemChecked (args);
285                                         }
286                                 } else
287                                         is_checked = value;
288                         }
289                 }
290
291                 [Browsable (false)]
292                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
293                 public bool Focused {
294                         get { 
295                                 if (owner == null)
296                                         return false;
297
298                                 // In virtual mode the checks are always done using indexes
299                                 if (owner.VirtualMode)
300                                         return Index == owner.focused_item_index;
301
302                                 // Light check
303                                 return owner.FocusedItem == this;
304
305                         }
306                         set {   
307                                 if (owner == null)
308                                         return;
309
310                                 if (Focused == value)
311                                         return;
312
313                                 ListViewItem prev_focused_item = owner.FocusedItem;
314                                 if (prev_focused_item != null)
315                                         prev_focused_item.UpdateFocusedState ();
316                                         
317                                 owner.focused_item_index = value ? Index : -1;
318                                 if (value)
319                                         owner.OnUIAFocusedItemChanged ();
320
321                                 UpdateFocusedState ();
322                         }
323                 }
324
325                 [Localizable (true)]
326                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
327                 public Font Font {
328                         get {
329                                 if (font != null)
330                                         return font;
331                                 else if (owner != null)
332                                         return owner.Font;
333
334                                 return ThemeEngine.Current.DefaultFont;
335                         }
336                         set {   
337                                 if (font == value)
338                                         return;
339
340                                 font = value; 
341                                 hot_font = null;
342
343                                 if (owner != null)
344                                         Layout ();
345                                 Invalidate ();
346                         }
347                 }
348
349                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
350                 public Color ForeColor {
351                         get {
352                                 if (sub_items.Count > 0)
353                                         return sub_items[0].ForeColor;
354
355                                 if (owner != null)
356                                         return owner.ForeColor;
357
358                                 return ThemeEngine.Current.ColorWindowText;
359                         }
360                         set { SubItems [0].ForeColor = value; }
361                 }
362
363                 [DefaultValue (-1)]
364                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
365                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
366                          typeof (System.Drawing.Design.UITypeEditor))]
367                 [Localizable (true)]
368                 [RefreshProperties (RefreshProperties.Repaint)]
369                 [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
370                 public int ImageIndex {
371                         get { return image_index; }
372                         set {
373                                 if (value < -1)
374                                         throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
375                                 
376                                 image_index = value;
377                                 image_key = String.Empty;
378
379                                 if (owner != null)
380                                         Layout ();
381                                 Invalidate ();
382                         }
383                 }
384
385                 [DefaultValue ("")]
386                 [LocalizableAttribute (true)]
387                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
388                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
389                          typeof (System.Drawing.Design.UITypeEditor))]
390                 [RefreshProperties (RefreshProperties.Repaint)]
391                 [TypeConverter (typeof (ImageKeyConverter))]
392                 public string ImageKey {
393                         get {
394                                 return image_key;
395                         }
396                         set {
397                                 image_key = value == null ? String.Empty : value;
398                                 image_index = -1;
399
400                                 if (owner != null)
401                                         Layout ();
402                                 Invalidate ();
403                         }
404                 }
405
406                 [Browsable (false)]
407                 public ImageList ImageList {
408                         get {
409                                 if (owner == null)
410                                         return null;
411                                 else if (owner.View == View.LargeIcon)
412                                         return owner.large_image_list;
413                                 else
414                                         return owner.small_image_list;
415                         }
416                 }
417
418                 [DefaultValue (0)]
419                 public int IndentCount {
420                         get {
421                                 return indent_count;
422                         }
423                         set {
424                                 if (value < 0)
425                                         throw new ArgumentOutOfRangeException ("value");
426
427                                 if (value == indent_count)
428                                         return;
429
430                                 indent_count = value;
431                                 Invalidate ();
432                         }
433                 }
434
435                 [Browsable (false)]
436                 public int Index {
437                         get {
438                                 if (owner == null)
439                                         return -1;
440                                 if (owner.VirtualMode)
441                                         return display_index;
442
443                                 if (display_index == -1)
444                                         return owner.Items.IndexOf (this);
445
446                                 return owner.GetItemIndex (display_index);
447                         }
448                 }
449
450                 [Browsable (false)]
451                 public ListView ListView {
452                         get { return owner; }
453                 }
454
455                 [Browsable (false)]
456                 [Localizable (true)]
457                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
458                 public string Name {
459                         get {
460                                 return name;
461                         }
462                         set {
463                                 name = value == null ? String.Empty : value;
464                         }
465                 }
466
467                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
468                 [Browsable (false)]
469                 public Point Position {
470                         get {
471                                 if (owner != null && owner.VirtualMode)
472                                         return owner.GetItemLocation (display_index);
473
474                                 if (owner != null && !owner.IsHandleCreated)
475                                         return new Point (-1, -1);
476
477                                 return position;
478                         }
479                         set {
480                                 if (owner == null || owner.View == View.Details || owner.View == View.List)
481                                         return;
482
483                                 if (owner.VirtualMode)
484                                         throw new InvalidOperationException ();
485
486                                 owner.ChangeItemLocation (display_index, value);
487                         }
488                 }
489
490                 // When ListView uses VirtualMode, selection state info
491                 // lives in the ListView, not in the item
492                 // Also, in VirtualMode we can't Reset() the selection
493                 [Browsable (false)]
494                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
495                 public bool Selected {
496                         get { 
497                                 if (owner != null && owner.VirtualMode)
498                                         return owner.SelectedIndices.Contains (Index);
499
500                                 return selected; 
501                         }
502                         set {
503                                 if (selected == value && owner != null && !owner.VirtualMode)
504                                         return;
505
506                                 SetSelectedCore (value);
507                         }
508                 }
509
510                 // Expose this method as internal so we can force an update in the selection.
511                 internal void SetSelectedCore (bool value)
512                 {
513                         if (owner != null) {
514                                 if (value && !owner.MultiSelect)
515                                         owner.SelectedIndices.Clear ();
516                                 if (owner.VirtualMode) {
517                                         if (value)
518                                                 owner.SelectedIndices.InsertIndex (Index);
519                                         else
520                                                 owner.SelectedIndices.RemoveIndex (Index);
521                                 } else {
522                                         selected = value;
523                                         owner.SelectedIndices.Reset (); // force re-population of list
524                                 }
525
526                                 owner.OnItemSelectionChanged (new ListViewItemSelectionChangedEventArgs (this, Index, value));
527                                 owner.OnSelectedIndexChanged ();
528                                 Invalidate ();
529                         } else
530                                 selected = value;
531                 }
532
533                 [DefaultValue (-1)]
534                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
535                          typeof (System.Drawing.Design.UITypeEditor))]
536                 [Localizable (true)]
537                 [RefreshProperties (RefreshProperties.Repaint)]
538                 [RelatedImageListAttribute ("ListView.StateImageList")]
539                 [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
540                 public int StateImageIndex {
541                         get { return state_image_index; }
542                         set {
543                                 if (value < -1 || value > 14)
544                                         throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
545
546                                 state_image_index = value;
547                         }
548                 }
549
550                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
551                 [Editor ("System.Windows.Forms.Design.ListViewSubItemCollectionEditor, " + Consts.AssemblySystem_Design,
552                          typeof (System.Drawing.Design.UITypeEditor))]
553                 public ListViewSubItemCollection SubItems {
554                         get {
555                                 if (sub_items.Count == 0)
556                                         this.sub_items.Add (string.Empty);
557                                 return sub_items;
558                         }
559                 }
560
561                 [Bindable (true)]
562                 [DefaultValue (null)]
563                 [Localizable (false)]
564                 [TypeConverter (typeof (StringConverter))]
565                 public object Tag {
566                         get { return tag; }
567                         set { tag = value; }
568                 }
569
570                 [Localizable (true)]
571                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
572                 public string Text {
573                         get {
574                                 if (this.sub_items.Count > 0)
575                                         return this.sub_items [0].Text;
576                                 else
577                                         return string.Empty;
578                         }
579                         set { 
580                                 if (SubItems [0].Text == value)
581                                         return;
582
583                                 sub_items [0].Text = value; 
584
585                                 if (owner != null)
586                                         Layout ();
587                                 Invalidate ();
588
589                                 //UIA Framework: Generates Text changed
590                                 OnUIATextChanged ();
591
592                         }
593                 }
594
595                 [DefaultValue (true)]
596                 public bool UseItemStyleForSubItems {
597                         get { return use_item_style; }
598                         set { use_item_style = value; }
599                 }
600
601                 [LocalizableAttribute(true)]
602                 [DefaultValue (null)]
603                 public ListViewGroup Group {
604                         get { return this.group; }
605                         set {
606                                 if (group != value) {
607                                         if (value == null)
608                                                 group.Items.Remove (this);
609                                         else
610                                                 value.Items.Add (this);
611                                 
612                                         group = value;
613                                 }
614                         }
615                 }
616
617                 [DefaultValue ("")]
618                 public string ToolTipText {
619                         get {
620                                 return tooltip_text;
621                         }
622                         set {
623                                 if (value == null)
624                                         value = String.Empty;
625
626                                 tooltip_text = value;
627                         }
628                 }
629
630                 #endregion      // Public Instance Properties
631
632                 #region Public Instance Methods
633                 public void BeginEdit ()
634                 {
635                         if (owner != null && owner.LabelEdit) {
636                                 owner.item_control.BeginEdit (this);
637                         }
638                         // FIXME: TODO
639                         // if (owner != null && owner.LabelEdit 
640                         //    && owner.Activation == ItemActivation.Standard)
641                         // allow editing
642                         // else
643                         // throw new InvalidOperationException ();
644                 }
645
646                 public virtual object Clone ()
647                 {
648                         ListViewItem clone = new ListViewItem ();
649                         clone.image_index = this.image_index;
650                         clone.is_checked = this.is_checked;
651                         clone.selected = this.selected;
652                         clone.font = this.font;
653                         clone.state_image_index = this.state_image_index;
654                         clone.sub_items = new ListViewSubItemCollection (this, null);
655                         
656                         foreach (ListViewSubItem subItem in this.sub_items)
657                                 clone.sub_items.Add (subItem.Text, subItem.ForeColor,
658                                                      subItem.BackColor, subItem.Font);
659                         clone.tag = this.tag;
660                         clone.use_item_style = this.use_item_style;
661                         clone.owner = null;
662                         clone.name = name;
663                         clone.tooltip_text = tooltip_text;
664
665                         return clone;
666                 }
667
668                 public virtual void EnsureVisible ()
669                 {
670                         if (this.owner != null) {
671                                 owner.EnsureVisible (owner.Items.IndexOf (this));
672                         }
673                 }
674
675                 public ListViewItem FindNearestItem (SearchDirectionHint searchDirection)
676                 {
677                         if (owner == null)
678                                 return null;
679
680                         Point loc = owner.GetItemLocation (display_index);
681                         return owner.FindNearestItem (searchDirection, loc);
682                 }
683
684                 public Rectangle GetBounds (ItemBoundsPortion portion)
685                 {
686                         if (owner == null)
687                                 return Rectangle.Empty;
688                                 
689                         Rectangle rect;
690
691                         switch (portion) {
692                         case ItemBoundsPortion.Icon:
693                                 rect = icon_rect;
694                                 break;
695
696                         case ItemBoundsPortion.Label:
697                                 rect = label_rect;
698                                 break;
699
700                         case ItemBoundsPortion.ItemOnly:
701                                 rect = item_rect;
702                                 break;
703
704                         case ItemBoundsPortion.Entire:
705                                 rect = bounds;
706                                 break;
707
708                         default:
709                                 throw new ArgumentException ("Invalid value for portion.");
710                         }
711
712                         Point item_loc = owner.GetItemLocation (DisplayIndex);
713                         rect.X += item_loc.X;
714                         rect.Y += item_loc.Y;
715                         return rect;
716                 }
717
718                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
719                 {
720                         Serialize (info, context);
721                 }
722
723                 public ListViewSubItem GetSubItemAt (int x, int y)
724                 {
725                         if (owner != null && owner.View != View.Details)
726                                 return null;
727
728                         foreach (ListViewSubItem sub_item in sub_items)
729                                 if (sub_item.Bounds.Contains (x, y))
730                                         return sub_item;
731
732                         return null;
733                 }
734
735                 public virtual void Remove ()
736                 {
737                         if (owner == null)
738                                 return;
739
740                         owner.item_control.CancelEdit (this);
741                         owner.Items.Remove (this);
742                         owner = null;
743                 }
744
745                 public override string ToString ()
746                 {
747                         return string.Format ("ListViewItem: {0}", this.Text);
748                 }
749                 #endregion      // Public Instance Methods
750
751                 #region Protected Methods
752                 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
753                 {
754                         sub_items = new ListViewSubItemCollection (this, null);
755                         int sub_items_count = 0;
756
757                         foreach (SerializationEntry entry in info) {
758                                 switch (entry.Name) {
759                                         case "Text":
760                                                 sub_items.Add ((string)entry.Value);
761                                                 break;
762                                         case "Font":
763                                                 font = (Font)entry.Value;
764                                                 break;
765                                         case "Checked":
766                                                 is_checked = (bool)entry.Value;
767                                                 break;
768                                         case "ImageIndex":
769                                                 image_index = (int)entry.Value;
770                                                 break;
771                                         case "StateImageIndex":
772                                                 state_image_index = (int)entry.Value;
773                                                 break;
774                                         case "UseItemStyleForSubItems":
775                                                 use_item_style = (bool)entry.Value;
776                                                 break;
777                                         case "SubItemCount":
778                                                 sub_items_count = (int)entry.Value;
779                                                 break;
780                                         case "Group":
781                                                 group = (ListViewGroup)entry.Value;
782                                                 break;
783                                         case "ImageKey":
784                                                 if (image_index == -1)
785                                                         image_key = (string)entry.Value;
786                                                 break;
787                                 }
788                         }
789
790                         Type subitem_type = typeof (ListViewSubItem);
791                         if (sub_items_count > 0) {
792                                 sub_items.Clear (); // .net fixup
793                                 Text = info.GetString ("Text");
794                                 for (int i = 0; i < sub_items_count - 1; i++)
795                                         sub_items.Add ((ListViewSubItem)info.GetValue ("SubItem" + (i + 1), subitem_type));
796                         }
797
798                         // After any sub item has been added.
799                         ForeColor = (Color)info.GetValue ("ForeColor", typeof (Color));
800                         BackColor = (Color)info.GetValue ("BackColor", typeof (Color));
801                 }
802
803                 protected virtual void Serialize (SerializationInfo info, StreamingContext context)
804                 {
805                         info.AddValue ("Text", Text);
806                         info.AddValue ("Font", Font);
807                         info.AddValue ("ImageIndex", image_index);
808                         info.AddValue ("Checked", is_checked);
809                         info.AddValue ("StateImageIndex", state_image_index);
810                         info.AddValue ("UseItemStyleForSubItems", use_item_style);
811                         info.AddValue ("BackColor", BackColor);
812                         info.AddValue ("ForeColor", ForeColor);
813                         info.AddValue ("ImageKey", image_key);
814                         info.AddValue ("Group", group);
815                         if (sub_items.Count > 1) {
816                                 info.AddValue ("SubItemCount", sub_items.Count);
817                                 for (int i = 1; i < sub_items.Count; i++) {
818                                         info.AddValue ("SubItem" + i, sub_items [i]);
819                                 }
820                         }
821                 }
822                 #endregion      // Protected Methods
823
824                 #region Private Internal Methods
825                 internal Rectangle CheckRectReal {
826                         get {
827                                 Rectangle rect = checkbox_rect;
828                                 Point item_loc = owner.GetItemLocation (DisplayIndex);
829                                 rect.X += item_loc.X;
830                                 rect.Y += item_loc.Y;
831                                 return rect;
832                         }
833                 }
834                 
835                 Rectangle text_bounds;
836                 internal Rectangle TextBounds {
837                         get {
838                                 // Call Layout() if it hasn't been called before.
839                                 if (owner.VirtualMode && bounds == new Rectangle (-1, -1, -1, -1))
840                                         Layout ();
841                                 Rectangle result = text_bounds;
842                                 Point loc = owner.GetItemLocation (DisplayIndex);
843                                 result.X += loc.X;
844                                 result.Y += loc.Y;
845                                 return result;
846                         }
847                 }
848
849                 internal int DisplayIndex {
850                         get {
851                                 // Special case for Details view
852                                 // and no columns (which means no Layout at all)
853                                 if (display_index == -1)
854                                         return owner.Items.IndexOf (this);
855
856                                 return display_index;
857                         }
858                         set {
859                                 display_index = value;
860                         }
861                 }
862
863                 internal bool Hot {
864                         get {
865                                 return Index == owner.HotItemIndex;
866                         }
867                 }
868
869                 internal Font HotFont {
870                         get {
871                                 if (hot_font == null)
872                                         hot_font = new Font (Font, Font.Style | FontStyle.Underline);
873
874                                 return hot_font;
875                         }
876                 }
877
878                 internal ListView Owner {
879                         set {
880                                 if (owner == value)
881                                         return;
882
883                                 owner = value;
884                         }
885                 }
886
887                 internal void SetGroup (ListViewGroup group)
888                 {
889                         this.group = group;
890                 }
891
892                 internal void SetPosition (Point position)
893                 {
894                         this.position = position;
895                 }
896
897                 // When focus changed, we need to invalidate area
898                 // with previous layout and with the new one
899                 void UpdateFocusedState ()
900                 {
901                         if (owner != null) {
902                                 Invalidate ();
903                                 Layout ();
904                                 Invalidate ();
905                         }
906                 }
907
908                 internal void Invalidate ()
909                 {
910                         if (owner == null || owner.item_control == null || owner.updating)
911                                 return;
912
913                         // Add some padding to bounds (focused extra space, selection)
914                         Rectangle rect = Bounds;
915                         rect.Inflate (1, 1);
916                         owner.item_control.Invalidate (rect);
917                 }
918
919                 internal void Layout ()
920                 {
921                         if (owner == null)
922                                 return;
923                         int item_ht;
924                         Rectangle total;
925                         Size text_size = owner.text_size;
926                         
927                         checkbox_rect = Rectangle.Empty;
928                         if (owner.CheckBoxes)
929                                 checkbox_rect.Size = owner.CheckBoxSize;
930                         switch (owner.View) {
931                         case View.Details:
932                                 // LAMESPEC: MSDN says, "In all views except the details
933                                 // view of the ListView, this value specifies the same
934                                 // bounding rectangle as the Entire value." Actually, it
935                                 // returns same bounding rectangles for Item and Entire
936                                 // values in the case of Details view.
937
938                                 int x_offset = 0;
939                                 if (owner.SmallImageList != null)
940                                         x_offset = indent_count * owner.SmallImageList.ImageSize.Width;
941
942                                 // Handle reordered column
943                                 if (owner.Columns.Count > 0)
944                                         checkbox_rect.X = owner.Columns[0].Rect.X + x_offset;
945
946                                 icon_rect = label_rect = Rectangle.Empty;
947                                 icon_rect.X = checkbox_rect.Right + 2;
948                                 item_ht = owner.ItemSize.Height;
949
950                                 if (owner.SmallImageList != null)
951                                         icon_rect.Width = owner.SmallImageList.ImageSize.Width;
952
953                                 label_rect.Height = icon_rect.Height = item_ht;
954                                 checkbox_rect.Y = item_ht - checkbox_rect.Height;
955
956                                 label_rect.X = icon_rect.Width > 0 ? icon_rect.Right + 1 : icon_rect.Right;
957
958                                 if (owner.Columns.Count > 0)
959                                         label_rect.Width = owner.Columns[0].Wd - label_rect.X + checkbox_rect.X;
960                                 else
961                                         label_rect.Width = text_size.Width;
962
963                                 SizeF text_sz = TextRenderer.MeasureString (Text, Font);
964                                 text_bounds = label_rect;
965                                 text_bounds.Width = (int) text_sz.Width;
966
967                                 item_rect = total = Rectangle.Union
968                                         (Rectangle.Union (checkbox_rect, icon_rect), label_rect);
969                                 bounds.Size = total.Size;
970
971                                 item_rect.Width = 0;
972                                 bounds.Width = 0;
973                                 for (int i = 0; i < owner.Columns.Count; i++) {
974                                         item_rect.Width += owner.Columns [i].Wd;
975                                         bounds.Width += owner.Columns [i].Wd;
976                                 }
977
978                                 // Bounds for sub items
979                                 int n = Math.Min (owner.Columns.Count, sub_items.Count);
980                                 for (int i = 0; i < n; i++) {
981                                         Rectangle col_rect = owner.Columns [i].Rect;
982                                         sub_items [i].SetBounds (col_rect.X, 0, col_rect.Width, item_ht);
983                                 }
984                                 break;
985
986                         case View.LargeIcon:
987                                 label_rect = icon_rect = Rectangle.Empty;
988
989                                 SizeF sz = TextRenderer.MeasureString (Text, Font);
990                                 if ((int) sz.Width > text_size.Width) {
991                                         if (Focused && owner.InternalContainsFocus) {
992                                                 int text_width = text_size.Width;
993                                                 StringFormat format = new StringFormat ();
994                                                 format.Alignment = StringAlignment.Center;
995                                                 sz = TextRenderer.MeasureString (Text, Font, text_width, format);
996                                                 text_size.Height = (int) sz.Height;
997                                         } else
998                                                 text_size.Height = 2 * (int) sz.Height;
999                                 }
1000
1001                                 if (owner.LargeImageList != null) {
1002                                         icon_rect.Width = owner.LargeImageList.ImageSize.Width;
1003                                         icon_rect.Height = owner.LargeImageList.ImageSize.Height;
1004                                 }
1005
1006                                 if (checkbox_rect.Height > icon_rect.Height)
1007                                         icon_rect.Y = checkbox_rect.Height - icon_rect.Height;
1008                                 else
1009                                         checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height;
1010
1011                                 if (text_size.Width <= icon_rect.Width) {
1012                                         icon_rect.X = checkbox_rect.Width + 1;
1013                                         label_rect.X = icon_rect.X + (icon_rect.Width - text_size.Width) / 2;
1014                                         label_rect.Y = icon_rect.Bottom + 2;
1015                                         label_rect.Size = text_size;
1016                                 } else {
1017                                         int centerX = text_size.Width / 2;
1018                                         icon_rect.X = checkbox_rect.Width + 1 + centerX - icon_rect.Width / 2;
1019                                         label_rect.X = checkbox_rect.Width + 1;
1020                                         label_rect.Y = icon_rect.Bottom + 2;
1021                                         label_rect.Size = text_size;
1022                                 }
1023
1024                                 item_rect = Rectangle.Union (icon_rect, label_rect);
1025                                 total = Rectangle.Union (item_rect, checkbox_rect);
1026                                 bounds.Size = total.Size;
1027                                 break;
1028
1029                         case View.List:
1030                         case View.SmallIcon:
1031                                 label_rect = icon_rect = Rectangle.Empty;
1032                                 icon_rect.X = checkbox_rect.Width + 1;
1033                                 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
1034
1035                                 if (owner.SmallImageList != null) {
1036                                         item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
1037                                         icon_rect.Width = owner.SmallImageList.ImageSize.Width;
1038                                         icon_rect.Height = owner.SmallImageList.ImageSize.Height;
1039                                 }
1040
1041                                 checkbox_rect.Y = item_ht - checkbox_rect.Height;
1042                                 label_rect.X = icon_rect.Right + 1;
1043                                 label_rect.Width = text_size.Width;
1044                                 label_rect.Height = icon_rect.Height = item_ht;
1045
1046                                 item_rect = Rectangle.Union (icon_rect, label_rect);
1047                                 total = Rectangle.Union (item_rect, checkbox_rect);
1048                                 bounds.Size = total.Size;
1049                                 break;
1050                         case View.Tile:
1051                                 if (!Application.VisualStylesEnabled)
1052                                         goto case View.LargeIcon;
1053
1054                                 label_rect = icon_rect = Rectangle.Empty;
1055
1056                                 if (owner.LargeImageList != null) {
1057                                         icon_rect.Width = owner.LargeImageList.ImageSize.Width;
1058                                         icon_rect.Height = owner.LargeImageList.ImageSize.Height;
1059                                 }
1060
1061                                 int separation = 2;
1062                                 SizeF tsize = TextRenderer.MeasureString (Text, Font);
1063                                 int main_item_height = (int) Math.Ceiling (tsize.Height);
1064                                 int main_item_width = (int) Math.Ceiling (tsize.Width);
1065                                 sub_items [0].bounds.Height = main_item_height;
1066
1067                                 // Set initial values for subitem's layout
1068                                 int total_height = main_item_height;
1069                                 int max_subitem_width = main_item_width;
1070                         
1071                                 int count = Math.Min (owner.Columns.Count, sub_items.Count);
1072                                 for (int i = 1; i < count; i++) { // Ignore first column and first subitem
1073                                         ListViewSubItem sub_item = sub_items [i];
1074                                         if (sub_item.Text == null || sub_item.Text.Length == 0)
1075                                                 continue;
1076
1077                                         tsize = TextRenderer.MeasureString (sub_item.Text, sub_item.Font);
1078                                 
1079                                         int width = (int)Math.Ceiling (tsize.Width);
1080                                         if (width > max_subitem_width)
1081                                                 max_subitem_width = width;
1082                                 
1083                                         int height = (int)Math.Ceiling (tsize.Height);
1084                                         total_height += height + separation;
1085                                 
1086                                         sub_item.bounds.Height = height;
1087                                 }
1088
1089                                 max_subitem_width = Math.Min (max_subitem_width, owner.TileSize.Width - (icon_rect.Width + 4));
1090                                 label_rect.X = icon_rect.Right + 4;
1091                                 label_rect.Y = owner.TileSize.Height / 2 - total_height / 2;
1092                                 label_rect.Width = max_subitem_width;
1093                                 label_rect.Height = total_height;
1094                         
1095                                 // Main item - always set bounds for it
1096                                 sub_items [0].SetBounds (label_rect.X, label_rect.Y, max_subitem_width, sub_items [0].bounds.Height);
1097
1098                                 // Second pass to assign bounds for every sub item
1099                                 int current_y = sub_items [0].bounds.Bottom + separation;
1100                                 for (int j = 1; j < count; j++) {
1101                                         ListViewSubItem sub_item = sub_items [j];
1102                                         if (sub_item.Text == null || sub_item.Text.Length == 0)
1103                                                 continue;
1104
1105                                         sub_item.SetBounds (label_rect.X, current_y, max_subitem_width, sub_item.bounds.Height);
1106                                         current_y += sub_item.Bounds.Height + separation;
1107                                 }
1108                                 
1109                                 item_rect = Rectangle.Union (icon_rect, label_rect);
1110                                 bounds.Size = item_rect.Size;
1111                                 break;
1112                         }
1113                         
1114                 }
1115                 #endregion      // Private Internal Methods
1116
1117                 #region Subclasses
1118
1119                 [DefaultProperty ("Text")]
1120                 [DesignTimeVisible (false)]
1121                 [Serializable]
1122                 [ToolboxItem (false)]
1123                 [TypeConverter (typeof(ListViewSubItemConverter))]
1124                 public class ListViewSubItem
1125                 {
1126                         [NonSerialized]
1127                         internal ListViewItem owner;
1128                         private string text = string.Empty;
1129                         private string name;
1130                         private object userData;
1131                         private SubItemStyle style;
1132                         [NonSerialized]
1133                         internal Rectangle bounds;
1134
1135                 
1136                         #region UIA Framework: Methods, Properties and Events
1137                 
1138                         [field:NonSerialized]
1139                         internal event EventHandler UIATextChanged;
1140
1141                         private void OnUIATextChanged ()
1142                         {
1143                                 if (UIATextChanged != null)
1144                                         UIATextChanged (this, EventArgs.Empty);
1145                         }
1146
1147                         #endregion // UIA Framework: Methods, Properties and Events
1148
1149                         
1150                         #region Public Constructors
1151                         public ListViewSubItem ()
1152                                 : this (null, string.Empty, Color.Empty,
1153                                         Color.Empty, null)
1154                         {
1155                         }
1156
1157                         public ListViewSubItem (ListViewItem owner, string text)
1158                                 : this (owner, text, Color.Empty,
1159                                         Color.Empty, null)
1160                         {
1161                         }
1162
1163                         public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
1164                                                 Color backColor, Font font)
1165                         {
1166                                 this.owner = owner;
1167                                 Text = text;
1168                                 this.style = new SubItemStyle (foreColor,
1169                                         backColor, font);
1170                         }
1171                         #endregion // Public Constructors
1172
1173                         #region Public Instance Properties
1174                         public Color BackColor {
1175                                 get {
1176                                         if (style.backColor != Color.Empty)
1177                                                 return style.backColor;
1178                                         if (this.owner != null && this.owner.ListView != null)
1179                                                 return this.owner.ListView.BackColor;
1180                                         return ThemeEngine.Current.ColorWindow;
1181                                 }
1182                                 set { 
1183                                         style.backColor = value;
1184                                         Invalidate ();
1185                                 }
1186                         }
1187
1188                         [Browsable (false)]
1189                         public Rectangle Bounds {
1190                                 get {
1191                                         Rectangle retval = bounds;
1192                                         if (owner != null) {
1193                                                 retval.X += owner.Bounds.X;
1194                                                 retval.Y += owner.Bounds.Y;
1195                                         }
1196
1197                                         return retval;
1198                                 }
1199                         }
1200
1201                         [Localizable (true)]
1202                         public Font Font {
1203                                 get {
1204                                         if (style.font != null)
1205                                                 return style.font;
1206                                         else if (owner != null)
1207                                                 return owner.Font;
1208                                         return ThemeEngine.Current.DefaultFont;
1209                                 }
1210                                 set {
1211                                         if (style.font == value)
1212                                                 return;
1213                                         style.font = value; 
1214                                         Invalidate ();
1215                                 }
1216                         }
1217
1218                         public Color ForeColor {
1219                                 get {
1220                                         if (style.foreColor != Color.Empty)
1221                                                 return style.foreColor;
1222                                         if (this.owner != null && this.owner.ListView != null)
1223                                                 return this.owner.ListView.ForeColor;
1224                                         return ThemeEngine.Current.ColorWindowText;
1225                                 }
1226                                 set {
1227                                         style.foreColor = value;
1228                                         Invalidate ();
1229                                 }
1230                         }
1231
1232                         [Localizable (true)]
1233                         public string Name {
1234                                 get {
1235                                         if (name == null)
1236                                                 return string.Empty;
1237                                         return name;
1238                                 }
1239                                 set {
1240                                         name = value;
1241                                 }
1242                         }
1243
1244                         [TypeConverter (typeof (StringConverter))]
1245                         [BindableAttribute (true)]
1246                         [DefaultValue (null)]
1247                         [Localizable (false)]
1248                         public object Tag {
1249                                 get {
1250                                         return userData;
1251                                 }
1252                                 set {
1253                                         userData = value;
1254                                 }
1255                         }
1256
1257                         [Localizable (true)]
1258                         public string Text {
1259                                 get { return text; }
1260                                 set { 
1261                                         if(text == value)
1262                                                 return;
1263
1264                                         if(value == null)
1265                                                 text = string.Empty;
1266                                         else
1267                                                 text = value; 
1268
1269                                         Invalidate ();
1270
1271                                         // UIA Framework: Generates SubItem TextChanged
1272                                         OnUIATextChanged ();
1273                                     }
1274                         }
1275                         #endregion // Public Instance Properties
1276
1277                         #region Public Methods
1278                         public void ResetStyle ()
1279                         {
1280                                 style.Reset ();
1281                                 Invalidate ();
1282                         }
1283
1284                         public override string ToString ()
1285                         {
1286                                 return string.Format ("ListViewSubItem {{0}}", text);
1287                         }
1288                         #endregion // Public Methods
1289
1290                         #region Private Methods
1291                         private void Invalidate ()
1292                         {
1293                                 if (owner == null || owner.owner == null)
1294                                         return;
1295
1296                                 owner.Invalidate ();
1297                         }
1298
1299                         [OnDeserialized]
1300                         void OnDeserialized (StreamingContext context)
1301                         {
1302                                 name = null;
1303                                 userData = null;
1304                         }
1305
1306                         internal int Height {
1307                                 get {
1308                                         return bounds.Height;
1309                                 }
1310                         }
1311
1312                         internal void SetBounds (int x, int y, int width, int height)
1313                         {
1314                                 bounds = new Rectangle (x, y, width, height);
1315                         }
1316
1317                         #endregion // Private Methods
1318
1319                         [Serializable]
1320                         class SubItemStyle
1321                         {
1322                                 public SubItemStyle ()
1323                                 {
1324                                 }
1325
1326                                 public SubItemStyle (Color foreColor, Color backColor, Font font)
1327                                 {
1328                                         this.foreColor = foreColor;
1329                                         this.backColor = backColor;
1330                                         this.font = font;
1331                                 }
1332
1333                                 public void Reset ()
1334                                 {
1335                                         foreColor = Color.Empty;
1336                                         backColor = Color.Empty;
1337                                         font = null;
1338                                 }
1339
1340                                 public Color backColor;
1341                                 public Color foreColor;
1342                                 public Font font;
1343                         }
1344                 }
1345
1346                 public class ListViewSubItemCollection : IList, ICollection, IEnumerable
1347                 {
1348                         private ArrayList list;
1349                         internal ListViewItem owner;
1350
1351                         #region Public Constructors
1352                         public ListViewSubItemCollection (ListViewItem owner) : this (owner, owner.Text)
1353                         {
1354                         }
1355                         #endregion // Public Constructors
1356
1357                         internal ListViewSubItemCollection (ListViewItem owner, string text)
1358                         {
1359                                 this.owner = owner;
1360                                 this.list = new ArrayList ();
1361                                 if (text != null)
1362                                         Add (text);
1363                         }
1364                         #region Public Properties
1365                         [Browsable (false)]
1366                         public int Count {
1367                                 get { return list.Count; }
1368                         }
1369
1370                         public bool IsReadOnly {
1371                                 get { return false; }
1372                         }
1373
1374                         public ListViewSubItem this [int index] {
1375                                 get { return (ListViewSubItem) list [index]; }
1376                                 set { 
1377                                         value.owner = owner;
1378                                         list [index] = value;
1379                                         owner.Layout ();
1380                                         owner.Invalidate ();
1381                                 }
1382                         }
1383
1384                         public virtual ListViewSubItem this [string key] {
1385                                 get {
1386                                         int idx = IndexOfKey (key);
1387                                         if (idx == -1)
1388                                                 return null;
1389
1390                                         return (ListViewSubItem) list [idx];
1391                                 }
1392                         }
1393
1394                         bool ICollection.IsSynchronized {
1395                                 get { return list.IsSynchronized; }
1396                         }
1397
1398                         object ICollection.SyncRoot {
1399                                 get { return list.SyncRoot; }
1400                         }
1401
1402                         bool IList.IsFixedSize {
1403                                 get { return list.IsFixedSize; }
1404                         }
1405
1406                         object IList.this [int index] {
1407                                 get { return this [index]; }
1408                                 set {
1409                                         if (! (value is ListViewSubItem))
1410                                                 throw new ArgumentException ("Not of type ListViewSubItem", "value");
1411                                         this [index] = (ListViewSubItem) value;
1412                                 }
1413                         }
1414                         #endregion // Public Properties
1415
1416                         #region Public Methods
1417                         public ListViewSubItem Add (ListViewSubItem item)
1418                         {
1419                                 AddSubItem (item);
1420                                 owner.Layout ();
1421                                 owner.Invalidate ();
1422                                 return item;
1423                         }
1424
1425                         public ListViewSubItem Add (string text)
1426                         {
1427                                 ListViewSubItem item = new ListViewSubItem (owner, text);
1428                                 return Add (item);
1429                         }
1430
1431                         public ListViewSubItem Add (string text, Color foreColor,
1432                                                     Color backColor, Font font)
1433                         {
1434                                 ListViewSubItem item = new ListViewSubItem (owner, text,
1435                                                                             foreColor, backColor, font);
1436                                 return Add (item);
1437                         }
1438
1439                         public void AddRange (ListViewSubItem [] items)
1440                         {
1441                                 if (items == null)
1442                                         throw new ArgumentNullException ("items");
1443
1444                                 foreach (ListViewSubItem item in items) {
1445                                         if (item == null)
1446                                                 continue;
1447                                         AddSubItem (item);
1448                                 }
1449                                 owner.Layout ();
1450                                 owner.Invalidate ();
1451                         }
1452
1453                         public void AddRange (string [] items)
1454                         {
1455                                 if (items == null)
1456                                         throw new ArgumentNullException ("items");
1457
1458                                 foreach (string item in items) {
1459                                         if (item == null)
1460                                                 continue;
1461                                         AddSubItem (new ListViewSubItem (owner, item));
1462                                 }
1463                                 owner.Layout ();
1464                                 owner.Invalidate ();
1465                         }
1466
1467                         public void AddRange (string [] items, Color foreColor,
1468                                               Color backColor, Font font)
1469                         {
1470                                 if (items == null)
1471                                         throw new ArgumentNullException ("items");
1472
1473                                 foreach (string item in items) {
1474                                         if (item == null)
1475                                                 continue;
1476
1477                                         AddSubItem (new ListViewSubItem (owner, item, foreColor, backColor, font));
1478                                 }
1479                                 owner.Layout ();
1480                                 owner.Invalidate ();
1481                         }
1482
1483                         void AddSubItem (ListViewSubItem subItem)
1484                         {
1485                                 subItem.owner = owner;
1486                                 list.Add (subItem);
1487
1488                                 //UIA Framework
1489                                 subItem.UIATextChanged += OnUIASubItemTextChanged;
1490                         }
1491
1492                         public void Clear ()
1493                         {
1494                                 list.Clear ();
1495                         }
1496
1497                         public bool Contains (ListViewSubItem subItem)
1498                         {
1499                                 return list.Contains (subItem);
1500                         }
1501
1502                         public virtual bool ContainsKey (string key)
1503                         {
1504                                 return IndexOfKey (key) != -1;
1505                         }
1506
1507                         public IEnumerator GetEnumerator ()
1508                         {
1509                                 return list.GetEnumerator ();
1510                         }
1511
1512                         void ICollection.CopyTo (Array dest, int index)
1513                         {
1514                                 list.CopyTo (dest, index);
1515                         }
1516
1517                         int IList.Add (object item)
1518                         {
1519                                 if (! (item is ListViewSubItem)) {
1520                                         throw new ArgumentException ("Not of type ListViewSubItem", "item");
1521                                 }
1522
1523                                 ListViewSubItem sub_item = (ListViewSubItem) item;
1524                                 sub_item.owner = this.owner;
1525                                 //UIA Framework
1526                                 sub_item.UIATextChanged += OnUIASubItemTextChanged;
1527                                 return list.Add (sub_item);
1528                         }
1529
1530                         bool IList.Contains (object subItem)
1531                         {
1532                                 if (! (subItem is ListViewSubItem)) {
1533                                         throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
1534                                 }
1535
1536                                 return this.Contains ((ListViewSubItem) subItem);
1537                         }
1538
1539                         int IList.IndexOf (object subItem)
1540                         {
1541                                 if (! (subItem is ListViewSubItem)) {
1542                                         throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
1543                                 }
1544
1545                                 return this.IndexOf ((ListViewSubItem) subItem);
1546                         }
1547
1548                         void IList.Insert (int index, object item)
1549                         {
1550                                 if (! (item is ListViewSubItem)) {
1551                                         throw new ArgumentException ("Not of type ListViewSubItem", "item");
1552                                 }
1553
1554                                 this.Insert (index, (ListViewSubItem) item);
1555                         }
1556
1557                         void IList.Remove (object item)
1558                         {
1559                                 if (! (item is ListViewSubItem)) {
1560                                         throw new ArgumentException ("Not of type ListViewSubItem", "item");
1561                                 }
1562
1563                                 this.Remove ((ListViewSubItem) item);
1564                         }
1565
1566                         public int IndexOf (ListViewSubItem subItem)
1567                         {
1568                                 return list.IndexOf (subItem);
1569                         }
1570
1571                         public virtual int IndexOfKey (string key)
1572                         {
1573                                 if (key == null || key.Length == 0)
1574                                         return -1;
1575
1576                                 for (int i = 0; i < list.Count; i++) {
1577                                         ListViewSubItem l = (ListViewSubItem) list [i];
1578                                         if (String.Compare (l.Name, key, true) == 0)
1579                                                 return i;
1580                                 }
1581
1582                                 return -1;
1583                         }
1584
1585                         public void Insert (int index, ListViewSubItem item)
1586                         {
1587                                 item.owner = this.owner;
1588                                 list.Insert (index, item);
1589                                 owner.Layout ();
1590                                 owner.Invalidate ();
1591
1592                                 //UIA Framework
1593                                 item.UIATextChanged += OnUIASubItemTextChanged;
1594                         }
1595
1596                         public void Remove (ListViewSubItem item)
1597                         {
1598                                 list.Remove (item);
1599                                 owner.Layout ();
1600                                 owner.Invalidate ();
1601
1602                                 //UIA Framework
1603                                 item.UIATextChanged -= OnUIASubItemTextChanged;
1604                         }
1605
1606                         public virtual void RemoveByKey (string key)
1607                         {
1608                                 int idx = IndexOfKey (key);
1609                                 if (idx != -1)
1610                                         RemoveAt (idx);
1611                         }
1612
1613                         public void RemoveAt (int index)
1614                         {
1615                                 //UIA Framework
1616                                 if (index >= 0 && index < list.Count)
1617                                         ((ListViewSubItem) list [index]).UIATextChanged -= OnUIASubItemTextChanged;
1618
1619                                 list.RemoveAt (index);
1620
1621                         }
1622                         #endregion // Public Methods
1623                         #region UIA Event Handler
1624                         
1625                         private void OnUIASubItemTextChanged (object sender, EventArgs args)
1626                         {
1627                                 owner.OnUIASubItemTextChanged (new LabelEditEventArgs (list.IndexOf (sender)));
1628                         }
1629
1630                         #endregion
1631
1632
1633                 }
1634                 #endregion // Subclasses
1635         }
1636 }