Merge pull request #943 from ermshiperete/bug-novell-325669
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ComboBox.cs
index 0b58f162f2660567612dd3be41ba284e0b1a8903..fad6981b745964226a9ff363374068cfde4946ef 100644 (file)
@@ -33,17 +33,16 @@ using System.Drawing;
 using System.Globalization;
 using System.Reflection;
 using System.Runtime.InteropServices;
+using System.Diagnostics;
 
 namespace System.Windows.Forms
 {
        [DefaultProperty("Items")]
        [DefaultEvent("SelectedIndexChanged")]
        [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
-#if NET_2_0
        [DefaultBindingProperty ("Text")]
        [ClassInterface (ClassInterfaceType.AutoDispatch)]
        [ComVisible(true)]
-#endif
        public class ComboBox : ListControl
        {
                private DrawMode draw_mode = DrawMode.Normal;
@@ -59,6 +58,7 @@ namespace System.Windows.Forms
                private ComboListBox listbox_ctrl;
                private ComboTextBox textbox_ctrl;
                private bool process_textchanged_event = true;
+               private bool process_texchanged_autoscroll = true;
                private bool item_height_specified;
                private int item_height;
                private int requested_height = -1;
@@ -71,13 +71,12 @@ namespace System.Windows.Forms
                private Rectangle listbox_area;
                private const int button_width = 16;
                bool drop_down_button_entered;
-#if NET_2_0
                private AutoCompleteStringCollection auto_complete_custom_source = null;
                private AutoCompleteMode auto_complete_mode = AutoCompleteMode.None;
                private AutoCompleteSource auto_complete_source = AutoCompleteSource.None;
-               private int drop_down_height;
                private FlatStyle flat_style;
-#endif
+               private int drop_down_height;
+               const int default_drop_down_height = 106;
 
                [ComVisible(true)]
                public class ChildAccessibleObject : AccessibleObject {
@@ -102,10 +101,8 @@ namespace System.Windows.Forms
                        background_color = ThemeEngine.Current.ColorWindow;
                        border_style = BorderStyle.None;
 
-#if NET_2_0
-                       drop_down_height = 106;
+                       drop_down_height = default_drop_down_height;
                        flat_style = FlatStyle.Standard;
-#endif
 
                        /* Events */
                        MouseDown += new MouseEventHandler (OnMouseDownCB);
@@ -126,8 +123,6 @@ namespace System.Windows.Forms
                        remove { base.BackgroundImageChanged -= value; }
                }
                
-#if NET_2_0
-
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public new event EventHandler BackgroundImageLayoutChanged
@@ -143,7 +138,6 @@ namespace System.Windows.Forms
                        add { base.DoubleClick += value; }
                        remove { base.DoubleClick -= value; }
                }
-#endif
 
                static object DrawItemEvent = new object ();
                static object DropDownEvent = new object ();
@@ -151,10 +145,8 @@ namespace System.Windows.Forms
                static object MeasureItemEvent = new object ();
                static object SelectedIndexChangedEvent = new object ();
                static object SelectionChangeCommittedEvent = new object ();
-#if NET_2_0
                static object DropDownClosedEvent = new object ();
                static object TextUpdateEvent = new object ();
-#endif
 
                public event DrawItemEventHandler DrawItem {
                        add { Events.AddHandler (DrawItemEvent, value); }
@@ -165,13 +157,11 @@ namespace System.Windows.Forms
                        add { Events.AddHandler (DropDownEvent, value); }
                        remove { Events.RemoveHandler (DropDownEvent, value); }
                }
-#if NET_2_0
                public event EventHandler DropDownClosed
                {
                        add { Events.AddHandler (DropDownClosedEvent, value); }
                        remove { Events.RemoveHandler (DropDownClosedEvent, value); }
                }
-#endif
 
                public event EventHandler DropDownStyleChanged {
                        add { Events.AddHandler (DropDownStyleChangedEvent, value); }
@@ -182,7 +172,6 @@ namespace System.Windows.Forms
                        add { Events.AddHandler (MeasureItemEvent, value); }
                        remove { Events.RemoveHandler (MeasureItemEvent, value); }
                }
-#if NET_2_0
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public new event EventHandler PaddingChanged
@@ -190,7 +179,6 @@ namespace System.Windows.Forms
                        add { base.PaddingChanged += value; }
                        remove { base.PaddingChanged -= value; }
                }
-#endif
                
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -208,18 +196,15 @@ namespace System.Windows.Forms
                        add { Events.AddHandler (SelectionChangeCommittedEvent, value); }
                        remove { Events.RemoveHandler (SelectionChangeCommittedEvent, value); }
                }
-#if NET_2_0
                public event EventHandler TextUpdate
                {
                        add { Events.AddHandler (TextUpdateEvent, value); }
                        remove { Events.RemoveHandler (TextUpdateEvent, value); }
                }
-#endif
 
                #endregion Events
 
                #region Public Properties
-#if NET_2_0
                [MonoTODO("AutoCompletion algorithm is currently not implemented.")]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
                [Browsable (true)]
@@ -304,7 +289,6 @@ namespace System.Windows.Forms
                                textbox_ctrl.AutoCompleteInternalSource = null;
                        }
                }
-#endif
                public override Color BackColor {
                        get { return base.BackColor; }
                        set {
@@ -327,20 +311,17 @@ namespace System.Windows.Forms
                        }
                }
 
-#if NET_2_0
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public override ImageLayout BackgroundImageLayout {
                        get { return base.BackgroundImageLayout; }
                        set { base.BackgroundImageLayout = value; }
                }
-#endif
 
                protected override CreateParams CreateParams {
                        get { return base.CreateParams;}
                }
 
-#if NET_2_0
                [DefaultValue ((string)null)]
                [AttributeProvider (typeof (IListSource))]
                [RefreshProperties (RefreshProperties.Repaint)]
@@ -349,7 +330,6 @@ namespace System.Windows.Forms
                        get { return base.DataSource; }
                        set { base.DataSource = value; }
                }
-#endif
 
                protected override Size DefaultSize {
                        get { return new Size (121, 21); }
@@ -376,7 +356,6 @@ namespace System.Windows.Forms
                        }
                }
 
-#if NET_2_0
                [Browsable (true)]
                [DefaultValue (106)]
                [EditorBrowsable (EditorBrowsableState.Always)]
@@ -389,11 +368,13 @@ namespace System.Windows.Forms
                                if (value < 1)
                                        throw new ArgumentOutOfRangeException ("DropDownHeight", "DropDownHeight must be greater than 0.");
                                        
+                               if (value == drop_down_height)
+                                       return;
+
                                drop_down_height = value;
                                IntegralHeight = false;
                        }
                }
-#endif
 
                [DefaultValue (ComboBoxStyle.DropDown)]
                [RefreshProperties(RefreshProperties.Repaint)]
@@ -452,12 +433,11 @@ namespace System.Windows.Forms
                                        textbox_ctrl.KeyPress += new KeyPressEventHandler (OnTextKeyPress);
                                        textbox_ctrl.Click += new EventHandler (OnTextBoxClick);
                                        textbox_ctrl.ContextMenu = ContextMenu;
+                                       textbox_ctrl.TopMargin = 1; // since we don't have borders, adjust manually the top
 
                                        if (IsHandleCreated == true)
                                                Controls.AddImplicit (textbox_ctrl);
-#if NET_2_0
                                        SetTextBoxAutoCompleteData ();
-#endif
                                }
                                
                                ResumeLayout ();
@@ -482,12 +462,8 @@ namespace System.Windows.Forms
                                        return;
                                        
                                if (value < 1)
-#if NET_2_0
                                        throw new ArgumentOutOfRangeException ("DropDownWidth",
                                                "The DropDownWidth value is less than one.");
-#else
-                                       throw new ArgumentException ("The DropDownWidth value is less than one.");
-#endif
 
                                dropdown_width = value;
                        }
@@ -509,11 +485,10 @@ namespace System.Windows.Forms
                                if (value) 
                                        DropDownListBox ();
                                else
-                                       listbox_ctrl.Hide ();
+                                       listbox_ctrl.HideWindow ();
                        }
                }
 
-#if NET_2_0
                [DefaultValue (FlatStyle.Standard)]
                [Localizable (true)]
                [MWFCategory("Appearance")]
@@ -528,7 +503,6 @@ namespace System.Windows.Forms
                                Invalidate ();
                        }
                }
-#endif
 
                public override bool Focused {
                        get { return base.Focused; }
@@ -570,12 +544,8 @@ namespace System.Windows.Forms
                        }
                        set {
                                if (value < 1)
-#if NET_2_0
                                        throw new ArgumentOutOfRangeException ("ItemHeight",
                                                "The item height value is less than one.");
-#else
-                                       throw new ArgumentException ("The item height value is less than one.");
-#endif
 
                                item_height_specified = true;
                                item_height = value;
@@ -589,9 +559,7 @@ namespace System.Windows.Forms
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
                [Localizable (true)]
                [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
-#if NET_2_0
                [MergableProperty (false)]
-#endif
                [MWFCategory("Data")]
                public ComboBox.ObjectCollection Items {
                        get { return items; }
@@ -609,14 +577,12 @@ namespace System.Windows.Forms
                        }
                }
 
-#if NET_2_0
                public override Size MaximumSize {
                        get { return base.MaximumSize; }
                        set {
                                base.MaximumSize = new Size (value.Width, 0);
                        }
                }
-#endif
 
                [DefaultValue (0)]
                [Localizable (true)]
@@ -638,7 +604,6 @@ namespace System.Windows.Forms
                        }
                }
 
-#if NET_2_0
                public override Size MinimumSize {
                        get { return base.MinimumSize; }
                        set {
@@ -653,7 +618,6 @@ namespace System.Windows.Forms
                        get { return base.Padding; }
                        set { base.Padding = value; }
                }
-#endif
 
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [Browsable (false)]
@@ -666,29 +630,7 @@ namespace System.Windows.Forms
                public override int SelectedIndex {
                        get { return selected_index; }
                        set {
-                               if (selected_index == value)
-                                       return;
-
-                               if (value <= -2 || value >= Items.Count)
-                                       throw new ArgumentOutOfRangeException ("SelectedIndex");
-                               selected_index = value;
-
-                               if (dropdown_style != ComboBoxStyle.DropDownList) {
-                                       if (value == -1)
-                                               SetControlText (string.Empty, false);
-                                       else
-                                               SetControlText (GetItemText (Items [value]), false);
-                               }
-
-                               if (DropDownStyle == ComboBoxStyle.DropDownList)
-                                       Invalidate ();
-
-                               if (listbox_ctrl != null)
-                                       listbox_ctrl.HighlightedIndex = value;
-
-                               OnSelectedValueChanged (new EventArgs ());
-                               OnSelectedIndexChanged (new EventArgs ());
-                               OnSelectedItemChanged (new EventArgs ());
+                               SetSelectedIndex (value, false);
                        }
                }
 
@@ -718,11 +660,6 @@ namespace System.Windows.Forms
                                        
                                string retval = textbox_ctrl.SelectedText;
                                
-#if ONLY_1_1
-                               // On 1.1, the textbox will return null, combobox returns ""
-                               if (retval == null && !textbox_ctrl.IsHandleCreated)
-                                       return string.Empty;
-#endif                                 
                                return retval;
                        }
                        set {
@@ -810,23 +747,24 @@ namespace System.Windows.Forms
                                        return;
                                }
 
-                               // do nothing if value exactly matches text of selected item
-                               if (SelectedItem != null && string.Compare (value, GetItemText (SelectedItem), false, CultureInfo.CurrentCulture) == 0)
-                                       return;
-
-                               // find exact match using case-sensitive comparison, and if does
-                               // not result in any match then use case-insensitive comparison
-                               int index = FindStringExact (value, -1, false);
-                               if (index == -1) {
-                                       index = FindStringExact (value, -1, true);
-                               }
-                               if (index != -1) {
-                                       SelectedIndex = index;
-                                       return;
+                               // don't set the index if value exactly matches text of selected item
+                               if (SelectedItem == null || string.Compare (value, GetItemText (SelectedItem), false, CultureInfo.CurrentCulture) != 0)
+                               {
+                                       // find exact match using case-sensitive comparison, and if does
+                                       // not result in any match then use case-insensitive comparison
+                                       int index = FindStringExact (value, -1, false);
+                                       if (index == -1) {
+                                               index = FindStringExact (value, -1, true);
+                                       }
+                                       if (index != -1) {
+                                               SelectedIndex = index;
+                                               return;
+                                       }
                                }
 
+                               // set directly the passed value
                                if (dropdown_style != ComboBoxStyle.DropDownList)
-                                       textbox_ctrl.Text = GetItemText (value);
+                                       textbox_ctrl.Text = value;
                        }
                }
 
@@ -848,12 +786,14 @@ namespace System.Windows.Forms
                        get { return textbox_ctrl; }
                }
 
+               internal ComboListBox UIAComboListBox {
+                       get { return listbox_ctrl; }
+               }
+
                #endregion UIA Framework Properties
 
                #region Public Methods
-#if NET_2_0
                [Obsolete ("This method has been deprecated")]
-#endif
                protected virtual void AddItemsCore (object[] value)
                {
                        
@@ -864,7 +804,6 @@ namespace System.Windows.Forms
                        suspend_ctrlupdate = true;
                }
 
-#if NET_2_0
                protected override AccessibleObject CreateAccessibilityInstance ()
                {
                        return base.CreateAccessibilityInstance ();
@@ -874,7 +813,6 @@ namespace System.Windows.Forms
                {
                        base.CreateHandle ();
                }
-#endif
 
                protected override void Dispose (bool disposing)
                {
@@ -912,18 +850,12 @@ namespace System.Windows.Forms
                        if (s == null || Items.Count == 0) 
                                return -1;
 
-#if NET_2_0
                        if (startIndex < -1 || startIndex >= Items.Count)
-#else
-                       if (startIndex < -1 || startIndex >= Items.Count - 1)
-#endif
                                throw new ArgumentOutOfRangeException ("startIndex");
 
                        int i = startIndex;
-#if NET_2_0
                        if (i == (Items.Count - 1))
                                i = -1;
-#endif
                        do {
                                i++;
                                if (string.Compare (s, 0, GetItemText (Items [i]), 0, s.Length, true) == 0)
@@ -950,18 +882,12 @@ namespace System.Windows.Forms
                        if (s == null || Items.Count == 0) 
                                return -1;
 
-#if NET_2_0
                        if (startIndex < -1 || startIndex >= Items.Count)
-#else
-                       if (startIndex < -1 || startIndex >= Items.Count - 1)
-#endif
                                throw new ArgumentOutOfRangeException ("startIndex");
 
                        int i = startIndex;
-#if NET_2_0
                        if (i == (Items.Count - 1))
                                i = -1;
-#endif
                        do {
                                i++;
                                if (string.Compare (s, GetItemText (Items [i]), ignoreCase, CultureInfo.CurrentCulture) == 0)
@@ -1024,6 +950,29 @@ namespace System.Windows.Forms
                        base.OnDataSourceChanged (e);
                        BindDataItems ();
                        
+                       /** 
+                        ** This 'Debugger.IsAttached' hack is here because of
+                        ** Xamarin Bug #2234, which noted that when changing
+                        ** the DataSource, in Windows exceptions are eaten
+                        ** when SelectedIndexChanged is fired.  However, when
+                        ** the debugger is running (i.e. in MonoDevelop), we
+                        ** want to be alerted of exceptions.
+                        **/
+
+                       if (Debugger.IsAttached) {
+                               SetSelectedIndex ();
+                       } else {
+                               try {
+                                       SetSelectedIndex ();
+                               } catch {
+                                       //ignore exceptions here per 
+                                       //bug 2234
+                               }
+                       }
+               }
+
+               private void SetSelectedIndex ()
+               {
                        if (DataSource == null || DataManager == null) {
                                SelectedIndex = -1;
                        } 
@@ -1039,28 +988,35 @@ namespace System.Windows.Forms
                        if (DataManager == null)
                                return;
 
+                       SelectedIndex = DataManager.Position;
+
                        if (selected_index != -1 && DropDownStyle != ComboBoxStyle.DropDownList)
                                SetControlText (GetItemText (Items [selected_index]), true);
 
                        if (!IsHandleCreated)
                                return;
 
-                       SelectedIndex = DataManager.Position;
                        Invalidate ();
                }
 
                protected virtual void OnDrawItem (DrawItemEventArgs e)
                {
+                       DrawItemEventHandler eh = (DrawItemEventHandler)(Events [DrawItemEvent]);
+                       if (eh != null)
+                               eh (this, e);
+               }
+
+               internal void HandleDrawItem (DrawItemEventArgs e)
+               {
+                       // Only raise OnDrawItem if we are in an OwnerDraw mode
                        switch (DrawMode) {
-                       case DrawMode.OwnerDrawFixed:
-                       case DrawMode.OwnerDrawVariable:
-                               DrawItemEventHandler eh = (DrawItemEventHandler)(Events [DrawItemEvent]);
-                               if (eh != null)
-                                       eh (this, e);
-                               break;
-                       default:
-                               ThemeEngine.Current.DrawComboBoxItem (this, e);
-                               break;
+                               case DrawMode.OwnerDrawFixed:
+                               case DrawMode.OwnerDrawVariable:
+                                       OnDrawItem (e);
+                                       break;
+                               default:
+                                       ThemeEngine.Current.DrawComboBoxItem (this, e);
+                                       break;
                        }
                }
 
@@ -1071,14 +1027,12 @@ namespace System.Windows.Forms
                                eh (this, e);
                }
 
-#if NET_2_0
                protected virtual void OnDropDownClosed (EventArgs e)
                {
                        EventHandler eh = (EventHandler) Events [DropDownClosedEvent];
                        if (eh != null)
                                eh (this, e);
                }
-#endif
 
                protected virtual void OnDropDownStyleChanged (EventArgs e)
                {
@@ -1094,10 +1048,8 @@ namespace System.Windows.Forms
                        if (textbox_ctrl != null)
                                textbox_ctrl.Font = Font;
                        
-                       if (!item_height_specified) {
-                               SizeF sz = TextRenderer.MeasureString ("The quick brown Fox", Font);
-                               item_height = (int) sz.Height;
-                       }
+                       if (!item_height_specified)
+                               item_height = Font.Height + 2;
 
                        if (IntegralHeight)
                                UpdateComboBoxBounds ();
@@ -1123,7 +1075,7 @@ namespace System.Windows.Forms
                        
                        if (textbox_ctrl != null) {
                                textbox_ctrl.SetSelectable (false);
-                               textbox_ctrl.ShowSelection = true;
+                               textbox_ctrl.ShowSelection = Enabled;
                                textbox_ctrl.ActivateCaret (true);
                                textbox_ctrl.SelectAll ();
                        }
@@ -1149,6 +1101,7 @@ namespace System.Windows.Forms
                                textbox_ctrl.ActivateCaret (false);
                                textbox_ctrl.ShowSelection = false;
                                textbox_ctrl.SelectionLength = 0;
+                               textbox_ctrl.HideAutoCompleteList ();
                        }
 
                        base.OnLostFocus (e);
@@ -1244,12 +1197,17 @@ namespace System.Windows.Forms
                                item_heights.Remove (Items [index]);
                }
 
-#if NET_2_0
                protected override void RefreshItems ()
                {
                        for (int i = 0; i < Items.Count; i++) {
                                RefreshItem (i);
                        }
+
+                       LayoutComboBox ();
+                       Refresh ();
+
+                       if (selected_index != -1 && DropDownStyle != ComboBoxStyle.DropDownList)
+                               SetControlText (GetItemText (Items [selected_index]), false);
                }
 
                public override void ResetText ()
@@ -1280,39 +1238,30 @@ namespace System.Windows.Forms
                        base.OnTextChanged (e);
                }
 
-#if NET_2_0
                protected virtual void OnTextUpdate (EventArgs e)
                {
                        EventHandler eh = (EventHandler) Events [TextUpdateEvent];
                        if (eh != null)
                                eh (this, e);
                }
-#endif
                protected override void OnMouseLeave (EventArgs e)
                {
-#if NET_2_0
                        if (flat_style == FlatStyle.Popup)
                                Invalidate ();
-#endif
                        base.OnMouseLeave (e);
                }
                
                protected override void OnMouseEnter (EventArgs e)
                {
-#if NET_2_0
                        if (flat_style == FlatStyle.Popup)
                                Invalidate ();
-#endif
                        base.OnMouseEnter (e);
                }
-#endif
 
-#if NET_2_0
                protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
                {
                        base.ScaleControl (factor, specified);
                }
-#endif
 
                public void Select (int start, int length)
                {
@@ -1384,13 +1333,19 @@ namespace System.Windows.Forms
                        case Msg.WM_KEYUP:
                        case Msg.WM_KEYDOWN:
                                Keys keys = (Keys) m.WParam.ToInt32 ();
+                               // Don't pass the message to base if auto complete is being used and available.
+                               if (textbox_ctrl != null && textbox_ctrl.CanNavigateAutoCompleteList) {
+                                       XplatUI.SendMessage (textbox_ctrl.Handle, (Msg) m.Msg, m.WParam, m.LParam);
+                                       return;
+                               }
                                if (keys == Keys.Up || keys == Keys.Down)
                                        break;
                                goto case Msg.WM_CHAR;
                        case Msg.WM_CHAR:
-                               if (textbox_ctrl != null)
+                               // Call our own handler first and send the message to the TextBox if still needed
+                               if (!ProcessKeyMessage (ref m) && textbox_ctrl != null)
                                        XplatUI.SendMessage (textbox_ctrl.Handle, (Msg) m.Msg, m.WParam, m.LParam);
-                               break;
+                               return;
                        case Msg.WM_MOUSELEAVE:
                                Point location = PointToClient (Control.MousePosition);
                                if (ClientRectangle.Contains (location))
@@ -1405,13 +1360,11 @@ namespace System.Windows.Forms
                #endregion Public Methods
 
                #region Private Methods
-#if NET_2_0
                void OnAutoCompleteCustomSourceChanged(object sender, CollectionChangeEventArgs e) {
                        if(auto_complete_source == AutoCompleteSource.CustomSource) {
                                //FIXME: handle add, remove and refresh events in AutoComplete algorithm.
                        }
                }
-#endif
 
                internal override bool InternalCapture {
                        get { return Capture; }
@@ -1439,13 +1392,11 @@ namespace System.Windows.Forms
                                button_area.Y = text_area.Y + border;
                                button_area.Width = button_width;
                                button_area.Height = text_area.Height - 2 * border;
-#if NET_2_0
                                if (flat_style == FlatStyle.Popup || flat_style == FlatStyle.Flat) {
                                        button_area.Inflate (1, 1);
                                        button_area.X += 2;
                                        button_area.Width -= 2;
                                }
-#endif
                        }
 
                        if (button_area != prev_button_area) {
@@ -1481,10 +1432,8 @@ namespace System.Windows.Forms
                        FlatStyle style = FlatStyle.Standard;
                        bool is_flat = false;
 
-#if NET_2_0
                        style = this.FlatStyle;
                        is_flat = style == FlatStyle.Flat || style == FlatStyle.Popup;
-#endif
 
                        theme.ComboBoxDrawBackground (this, dc, clip, style);
 
@@ -1493,6 +1442,8 @@ namespace System.Windows.Forms
                        // No edit control, we paint the edit ourselves
                        if (dropdown_style == ComboBoxStyle.DropDownList) {
                                DrawItemState state = DrawItemState.None;
+                               Color back_color = BackColor;
+                               Color fore_color = ForeColor;
                                Rectangle item_rect = text_area;
                                item_rect.X += border;
                                item_rect.Y += border;
@@ -1502,10 +1453,12 @@ namespace System.Windows.Forms
                                if (Focused) {
                                        state = DrawItemState.Selected;
                                        state |= DrawItemState.Focus;
+                                       back_color = SystemColors.Highlight;
+                                       fore_color = SystemColors.HighlightText;
                                }
                                
                                state |= DrawItemState.ComboBoxEdit;
-                               OnDrawItem (new DrawItemEventArgs (dc, Font, item_rect, SelectedIndex, state, ForeColor, BackColor));
+                               HandleDrawItem (new DrawItemEventArgs (dc, Font, item_rect, SelectedIndex, state, fore_color, back_color));
                        }
                        
                        if (show_dropdown_button) {
@@ -1551,6 +1504,9 @@ namespace System.Windows.Forms
 
                        FindMatchOrSetIndex(SelectedIndex);
 
+                       if (textbox_ctrl != null)
+                               textbox_ctrl.HideAutoCompleteList ();
+
                        if (listbox_ctrl.ShowWindow ())
                                dropped_down = true;
 
@@ -1568,9 +1524,7 @@ namespace System.Windows.Forms
                        button_state = ButtonState.Normal;
                        Invalidate (button_area);
                        dropped_down = false;
-#if NET_2_0
                        OnDropDownClosed (EventArgs.Empty);
-#endif
                        /*
                         * Apples X11 looses override-redirect when doing a Unmap/Map on a previously mapped window
                         * this causes the popup to appear under the main form.  This is horrible but necessary
@@ -1582,6 +1536,10 @@ namespace System.Windows.Forms
                                listbox_ctrl.Dispose ();
                                listbox_ctrl = null;
                        }
+                        // The auto complete list could have been shown after the listbox,
+                        // so make sure it's hidden.
+                        if (textbox_ctrl != null)
+                                textbox_ctrl.HideAutoCompleteList ();
                }
                
                private int FindStringCaseInsensitive (string search)
@@ -1646,6 +1604,10 @@ namespace System.Windows.Forms
                        if (Items.Count == 0)
                                return;
 
+                       // for keyboard navigation, we have to do our own scroll, since
+                       // the default behaviour for the SelectedIndex property is a little different,
+                       // setting the selected index in the top always
+
                        int offset;
                        switch (e.KeyCode) 
                        {
@@ -1673,7 +1635,7 @@ namespace System.Windows.Forms
                                        if (offset < 1)
                                                offset = 1;
 
-                                       SelectedIndex = Math.Max (SelectedIndex - offset, 0);
+                                       SetSelectedIndex (Math.Max (SelectedIndex - offset, 0), true);
 
                                        if (DroppedDown)
                                                if (SelectedIndex < listbox_ctrl.FirstVisibleItem ())
@@ -1691,7 +1653,7 @@ namespace System.Windows.Forms
                                        if (offset < 1)
                                                offset = 1;
 
-                                       SelectedIndex = Math.Min (SelectedIndex + offset, Items.Count - 1);
+                                       SetSelectedIndex (Math.Min (SelectedIndex + offset, Items.Count - 1), true);
 
                                        if (DroppedDown)
                                                if (SelectedIndex >= listbox_ctrl.LastVisibleItem ())
@@ -1700,7 +1662,8 @@ namespace System.Windows.Forms
                                
                                case Keys.Enter:        
                                case Keys.Escape:
-                                       DropDownListBoxFinished ();
+                                       if (listbox_ctrl != null && listbox_ctrl.Visible)
+                                               DropDownListBoxFinished ();
                                        break;
                                        
                                case Keys.Home:
@@ -1715,7 +1678,7 @@ namespace System.Windows.Forms
                                        break;
                                case Keys.End:
                                        if (dropdown_style == ComboBoxStyle.DropDownList) {
-                                               SelectedIndex = Items.Count - 1;
+                                               SetSelectedIndex (Items.Count - 1, true);
 
                                                if (DroppedDown)
                                                        if (SelectedIndex >= listbox_ctrl.LastVisibleItem ())
@@ -1728,6 +1691,34 @@ namespace System.Windows.Forms
                        }
                }
 
+               void SetSelectedIndex (int value, bool supressAutoScroll)
+               {
+                       if (selected_index == value)
+                               return;
+
+                       if (value <= -2 || value >= Items.Count)
+                               throw new ArgumentOutOfRangeException ("SelectedIndex");
+
+                       selected_index = value;
+
+                       if (dropdown_style != ComboBoxStyle.DropDownList) {
+                               if (value == -1)
+                                       SetControlText (string.Empty, false, supressAutoScroll);
+                               else
+                                       SetControlText (GetItemText (Items [value]), false, supressAutoScroll);
+                       }
+
+                       if (DropDownStyle == ComboBoxStyle.DropDownList)
+                               Invalidate ();
+
+                       if (listbox_ctrl != null)
+                               listbox_ctrl.HighlightedIndex = value;
+
+                       OnSelectedValueChanged (EventArgs.Empty);
+                       OnSelectedIndexChanged (EventArgs.Empty);
+                       OnSelectedItemChanged (EventArgs.Empty);
+               }
+
                // If no item is currently selected, and an item is found matching the text 
                // in the textbox, then selected that item.  Otherwise the item at the given 
                // index is selected.
@@ -1737,9 +1728,9 @@ namespace System.Windows.Forms
                        if (SelectedIndex == -1 && Text.Length != 0)
                                match = FindStringCaseInsensitive(Text);
                        if (match != -1)
-                               SelectedIndex = match;
+                               SetSelectedIndex (match, true);
                        else
-                               SelectedIndex = index;
+                               SetSelectedIndex (index, true);
                }
                
                void OnMouseDownCB (object sender, MouseEventArgs e)
@@ -1828,6 +1819,12 @@ namespace System.Windows.Forms
                        }
                }
 
+               MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
+               {
+                       Point loc = PointToClient (Control.MousePosition);
+                       return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
+               }
+
                internal override void OnPaintInternal (PaintEventArgs pevent)
                {
                        if (suspend_ctrlupdate)
@@ -1855,13 +1852,10 @@ namespace System.Windows.Forms
                                return;
                        }
                        
-                       // TODO:  THIS IS BROKEN-ISH
-                       // I don't think we should hilight, and setting the top item does weirdness
-                       // when there is no scrollbar
-                       
                        if (listbox_ctrl != null) {
-                               listbox_ctrl.SetTopItem (item);
-                               listbox_ctrl.HighlightedIndex = item;
+                               // Set as top item
+                               if (process_texchanged_autoscroll)
+                                       listbox_ctrl.EnsureTop (item);
                        }
 
                        base.Text = textbox_ctrl.Text;
@@ -1870,16 +1864,26 @@ namespace System.Windows.Forms
                private void OnTextKeyPress (object sender, KeyPressEventArgs e)
                {
                        selected_index = -1;
+                       if (listbox_ctrl != null)
+                               listbox_ctrl.HighlightedIndex = -1;
                }
 
                internal void SetControlText (string s, bool suppressTextChanged)
+               {
+                       SetControlText (s, suppressTextChanged, false);
+               }
+
+               internal void SetControlText (string s, bool suppressTextChanged, bool supressAutoScroll)
                {
                        if (suppressTextChanged)
                                process_textchanged_event = false;
+                       if (supressAutoScroll)
+                               process_texchanged_autoscroll = false;
                                
                        textbox_ctrl.Text = s;
                        textbox_ctrl.SelectAll ();
                        process_textchanged_event = true;
+                       process_texchanged_autoscroll = true;
                }
                
                void UpdateComboBoxBounds ()
@@ -1932,7 +1936,6 @@ namespace System.Windows.Forms
                        
                        #region UIA Framework Events
 
-#if NET_2_0
                        //NOTE:
                        //      We are using Reflection to add/remove internal events.
                        //      Class ListProvider uses the events.
@@ -1952,7 +1955,6 @@ namespace System.Windows.Forms
                                if (eh != null)
                                        eh (owner, args);
                        }
-#endif
 
                        #endregion UIA Framework Events
 
@@ -1985,25 +1987,23 @@ namespace System.Windows.Forms
                                        if (value == null)
                                                throw new ArgumentNullException ("value");
 
-#if NET_2_0
                                        //UIA Framework event: Item Removed
-                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
-#endif
+                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, object_items [index]));
 
                                        object_items[index] = value;
                                        
-#if NET_2_0
                                        //UIA Framework event: Item Added
-                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
-#endif
+                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
 
                                        if (owner.listbox_ctrl != null)
                                                owner.listbox_ctrl.InvalidateItem (index);
                                        if (index == owner.SelectedIndex) {
                                                if (owner.textbox_ctrl == null)
                                                        owner.Refresh ();
-                                               else
-                                                       owner.textbox_ctrl.SelectedText = value.ToString ();
+                                               else {
+                                                       owner.textbox_ctrl.Text = value.ToString ();
+                                                       owner.textbox_ctrl.SelectAll ();
+                                               }
                                        }
                                }
                        }
@@ -2027,7 +2027,7 @@ namespace System.Windows.Forms
                        {
                                int idx;
 
-                               idx = AddItem (item);
+                               idx = AddItem (item, false);
                                owner.UpdatedItems ();
                                return idx;
                        }
@@ -2038,8 +2038,11 @@ namespace System.Windows.Forms
                                        throw new ArgumentNullException ("items");
 
                                foreach (object mi in items)
-                                       AddItem (mi);
-                                       
+                                       AddItem (mi, true);
+
+                               if (owner.sorted)
+                                       Sort ();
+                               
                                owner.UpdatedItems ();
                        }
 
@@ -2050,10 +2053,8 @@ namespace System.Windows.Forms
                                owner.UpdatedItems ();
                                owner.Refresh ();
                                
-#if NET_2_0
                                //UIA Framework event: Items list cleared
-                               OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
-#endif
+                               OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
                        }
                        
                        public bool Contains (object value)
@@ -2064,7 +2065,6 @@ namespace System.Windows.Forms
                                return object_items.Contains (value);
                        }
 
-#if NET_2_0
                        public void CopyTo (object [] destination, int arrayIndex)
                        {
                                object_items.CopyTo (destination, arrayIndex);
@@ -2074,17 +2074,6 @@ namespace System.Windows.Forms
                        {
                                object_items.CopyTo (destination, index);
                        }
-#else
-                       public void CopyTo (object [] dest, int arrayIndex)
-                       {
-                               object_items.CopyTo (dest, arrayIndex);
-                       }
-
-                       void ICollection.CopyTo (Array dest, int index)
-                       {
-                               object_items.CopyTo (dest, index);
-                       }
-#endif
 
                        public IEnumerator GetEnumerator ()
                        {
@@ -2114,13 +2103,11 @@ namespace System.Windows.Forms
                                owner.BeginUpdate ();
                                
                                if (owner.Sorted)
-                                       AddItem (item);
+                                       AddItem (item, false);
                                else {
                                        object_items.Insert (index, item);
-#if NET_2_0
                                        //UIA Framework event: Item added
-                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
-#endif                                 
+                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
                                }
                                
                                owner.EndUpdate ();     // Calls UpdatedItems
@@ -2130,11 +2117,9 @@ namespace System.Windows.Forms
                        {
                                if (value == null)
                                        return;
-
-                               if (IndexOf (value) == owner.SelectedIndex)
-                                       owner.SelectedIndex = -1;
-                               
-                               RemoveAt (IndexOf (value));
+                               int index = IndexOf (value);
+                               if (index >= 0)
+                                       RemoveAt (index);
                        }
 
                        public void RemoveAt (int index)
@@ -2142,26 +2127,30 @@ namespace System.Windows.Forms
                                if (index < 0 || index >= Count)
                                        throw new ArgumentOutOfRangeException ("index");
                                        
-                               if (index == owner.SelectedIndex)
+                               if (index < owner.SelectedIndex)
+                                       --owner.SelectedIndex;
+                               else if (index == owner.SelectedIndex)
                                        owner.SelectedIndex = -1;
 
+                               object removed = object_items [index];
+
                                object_items.RemoveAt (index);
                                owner.UpdatedItems ();
                                
-#if NET_2_0
                                //UIA Framework event: Item removed
-                               OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
-#endif
+                               OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, removed));
                        }
                        #endregion Public Methods
 
                        #region Private Methods
-                       private int AddItem (object item)
+                       private int AddItem (object item, bool suspend)
                        {
+                               // suspend means do not sort as we put new items in, we will do a
+                               // big sort at the end
                                if (item == null)
                                        throw new ArgumentNullException ("item");
 
-                               if (owner.Sorted) {
+                               if (owner.Sorted && !suspend) {
                                        int index = 0;
                                        foreach (object o in object_items) {
                                                if (String.Compare (item.ToString (), o.ToString ()) < 0) {
@@ -2173,10 +2162,8 @@ namespace System.Windows.Forms
                                                        if (index <= owner.selected_index && owner.IsHandleCreated)
                                                                owner.selected_index++;
                                                                
-#if NET_2_0
                                                        //UIA Framework event: Item added
-                                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
-#endif
+                                                       OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
 
                                                        return index;
                                                }
@@ -2185,10 +2172,8 @@ namespace System.Windows.Forms
                                }
                                object_items.Add (item);
                                
-#if NET_2_0
                                //UIA Framework event: Item added
-                               OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, object_items.Count - 1));
-#endif
+                               OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
                                
                                return object_items.Count - 1;
                        }
@@ -2196,16 +2181,40 @@ namespace System.Windows.Forms
                        internal void AddRange (IList items)
                        {
                                foreach (object mi in items)
-                                       AddItem (mi);
+                                       AddItem (mi, false);
+                               
+                               if (owner.sorted)
+                                       Sort ();
                                
                                owner.UpdatedItems ();
                        }
 
                        internal void Sort ()
                        {
-                               object_items.Sort ();
+                               // If the objects the user put here don't have their own comparer,
+                               // use one that compares based on the object's ToString
+                               if (object_items.Count > 0 && object_items[0] is IComparer)
+                                       object_items.Sort ();
+                               else
+                                       object_items.Sort (new ObjectComparer (owner));
                        }
 
+                       private class ObjectComparer : IComparer
+                       {
+                               private ListControl owner;
+                               
+                               public ObjectComparer (ListControl owner)
+                               {
+                                       this.owner = owner;
+                               }
+                               
+                               #region IComparer Members
+                               public int Compare (object x, object y)
+                               {
+                                       return string.Compare (owner.GetItemText (x), owner.GetItemText (y));
+                               }
+                               #endregion
+                       }
                        #endregion Private Methods
                }
 
@@ -2217,7 +2226,33 @@ namespace System.Windows.Forms
                        {
                                this.owner = owner;
                                ShowSelection = false;
-                               HideSelection = false;
+                               owner.EnabledChanged += OwnerEnabledChangedHandler;
+                               owner.LostFocus += OwnerLostFocusHandler;
+                       }
+
+                       void OwnerEnabledChangedHandler (object o, EventArgs args)
+                       {
+                               ShowSelection = owner.Focused && owner.Enabled;
+                       }
+
+                       void OwnerLostFocusHandler (object o, EventArgs args)
+                       {
+                               if (IsAutoCompleteAvailable)
+                                       owner.Text = Text;
+                       }
+
+                       protected override void OnKeyDown (KeyEventArgs args)
+                       {
+                               if (args.KeyCode == Keys.Enter && IsAutoCompleteAvailable)
+                                       owner.Text = Text;
+
+                               base.OnKeyDown (args);
+                       }
+
+                       internal override void OnAutoCompleteValueSelected (EventArgs args)
+                       {
+                               base.OnAutoCompleteValueSelected (args);
+                               owner.Text = Text;
                        }
 
                        internal void SetSelectable (bool selectable)
@@ -2233,13 +2268,11 @@ namespace System.Windows.Forms
                                        document.CaretLostFocus ();
                        }
                        
-#if NET_2_0
                        internal override void OnTextUpdate ()
                        {
                                base.OnTextUpdate ();
                                owner.OnTextUpdate (EventArgs.Empty);
                        }
-#endif
                        
                        protected override void OnGotFocus (EventArgs e)
                        {
@@ -2251,12 +2284,47 @@ namespace System.Windows.Forms
                                owner.Select (false, true);
                        }
 
+                       // We have to pass these events to our owner - MouseMove is not, however.
+
+                       protected override void OnMouseDown (MouseEventArgs e)
+                       {
+                               base.OnMouseDown (e);
+                               owner.OnMouseDown (owner.TranslateMouseEventArgs (e));
+                       }
+
+                       protected override void OnMouseUp (MouseEventArgs e)
+                       {
+                               base.OnMouseUp (e);
+                               owner.OnMouseUp (owner.TranslateMouseEventArgs (e));
+                       }
+
+                       protected override void OnMouseClick (MouseEventArgs e)
+                       {
+                               base.OnMouseClick (e);
+                               owner.OnMouseClick (owner.TranslateMouseEventArgs (e));
+                       }
+
+                       protected override void OnMouseDoubleClick (MouseEventArgs e)
+                       {
+                               base.OnMouseDoubleClick (e);
+                               owner.OnMouseDoubleClick (owner.TranslateMouseEventArgs (e));
+                       }
+
                        public override bool Focused {
                                get {
                                        return owner.Focused;
                                }
                        }
-                       
+                       protected override void Dispose(bool disposing)
+                       {
+                               if (disposing ) {
+                                       // Prevents corruption of combobox text by disposed object
+                                       owner.EnabledChanged -= OwnerEnabledChangedHandler;
+                                       owner.LostFocus -= OwnerLostFocusHandler;
+                               }
+                               base.Dispose(disposing);
+                       }
+
                        internal override bool ActivateOnShow { get { return false; } }
                }
 
@@ -2278,6 +2346,22 @@ namespace System.Windows.Forms
                                NextPage,
                                PreviousPage,
                        }
+
+                       #region UIA Framework: Properties
+
+                       internal int UIATopItem {
+                               get { return top_item; }
+                       }
+                       
+                       internal int UIALastItem {
+                               get { return last_item; }
+                       }
+
+                       internal ScrollBar UIAVScrollBar {
+                               get { return vscrollbar_ctrl; }
+                       }
+
+                       #endregion
                        
                        class VScrollBarLB : VScrollBar
                        {
@@ -2375,42 +2459,48 @@ namespace System.Windows.Forms
                        internal void CalcListBoxArea ()
                        {
                                int width, height;
-                               bool show_scrollbar = false;
+                               bool show_scrollbar;
 
                                if (owner.DropDownStyle == ComboBoxStyle.Simple) {
                                        Rectangle area = owner.listbox_area;
                                        width = area.Width;
                                        height = area.Height;
+                                       show_scrollbar = owner.Items.Count * owner.ItemHeight > height;
 
                                        // No calculation needed
                                        if (height <= 0 || width <= 0)
                                                return;
+
                                }
                                else { // DropDown or DropDownList
                                        
                                        width = owner.DropDownWidth;
-                                       int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
+                                       int visible_items_count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
                                        
                                        if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
                                                height = 0;
-                                               for (int i = 0; i < count; i++) {
+                                               for (int i = 0; i < visible_items_count; i++) {
                                                        height += owner.GetItemHeight (i);
                                                }
+
+                                               show_scrollbar = owner.Items.Count > owner.MaxDropDownItems;
                                                
                                        } else  {
-#if NET_2_0
-                                               height = owner.DropDownHeight;
-#else          
-                                               height = owner.ItemHeight * count;
-#endif
+                                               if (owner.DropDownHeight == default_drop_down_height) { // ignore DropDownHeight
+                                                       height = owner.ItemHeight * visible_items_count;
+                                                       show_scrollbar = owner.Items.Count > owner.MaxDropDownItems;
+                                               } else {
+                                                       // ignore visible items count, and use manual height instead
+                                                       height = owner.DropDownHeight;
+                                                       show_scrollbar = (owner.Items.Count * owner.ItemHeight) > height;
+                                               }
                                        }
                                }
                                
                                page_size = Math.Max (height / owner.ItemHeight, 1);
 
                                ComboBoxStyle dropdown_style = owner.DropDownStyle;
-                               if ((dropdown_style != ComboBoxStyle.Simple && owner.Items.Count <= owner.MaxDropDownItems)
-                                       || (dropdown_style == ComboBoxStyle.Simple && owner.Items.Count * owner.ItemHeight < height)) {
+                               if (!show_scrollbar) {
 
                                        if (vscrollbar_ctrl != null)
                                                vscrollbar_ctrl.Visible = false;
@@ -2431,15 +2521,11 @@ namespace System.Windows.Forms
                                        vscrollbar_ctrl.Dock = DockStyle.Right;
 
                                        vscrollbar_ctrl.Maximum = owner.Items.Count - 1;
-#if NET_2_0
                                        int large = page_size;
-#else
-                                       int large = (dropdown_style == ComboBoxStyle.Simple ? page_size : owner.maxdrop_items) - 1;
-#endif
                                        if (large < 1)
                                                large = 1;
                                        vscrollbar_ctrl.LargeChange = large;
-                                       show_scrollbar = vscrollbar_ctrl.Visible = true;
+                                       vscrollbar_ctrl.Visible = true;
 
                                        int hli = HighlightedIndex;
                                        if (hli > 0) {
@@ -2447,12 +2533,14 @@ namespace System.Windows.Forms
                                                vscrollbar_ctrl.Value = hli;
                                        }
                                }
-                               
-                               Size = new Size (width, height);
-                               textarea_drawable = ClientRectangle;
-                               textarea_drawable.Width = width;
-                               textarea_drawable.Height = height;
-                               
+
+                               var borderWidth = Hwnd.GetBorderWidth (CreateParams);
+                               var borderAdjustment = dropdown_style == ComboBoxStyle.Simple ? new Size (0, 0) :
+                                       new Size (borderWidth.top + borderWidth.bottom, borderWidth.left + borderWidth.right);
+                               Size = new Size (width, height + borderAdjustment.Height);
+                               textarea_drawable = new Rectangle (ClientRectangle.Location,
+                                       new Size (width - borderAdjustment.Width, height));
+
                                if (vscrollbar_ctrl != null && show_scrollbar)
                                        textarea_drawable.Width -= vscrollbar_ctrl.Width;
 
@@ -2472,17 +2560,21 @@ namespace System.Windows.Forms
                                                        continue;
 
                                                DrawItemState state = DrawItemState.None;
+                                               Color back_color = owner.BackColor;
+                                               Color fore_color = owner.ForeColor;
 
                                                if (i == HighlightedIndex) {
                                                        state |= DrawItemState.Selected;
+                                                       back_color = SystemColors.Highlight;
+                                                       fore_color = SystemColors.HighlightText;
                                                        
                                                        if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
                                                                state |= DrawItemState.Focus;
                                                        }
                                                }
-                                               
-                                               owner.OnDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
-                                                       i, state, owner.ForeColor, owner.BackColor));
+
+                                               owner.HandleDrawItem (new DrawItemEventArgs (dc, owner.Font, item_rect,
+                                                       i, state, fore_color, back_color));
                                        }
                                }
                        }
@@ -2578,7 +2670,23 @@ namespace System.Windows.Forms
                        {
                                return top_item;
                        }
-                       
+
+                       public void EnsureTop (int item)
+                       {
+                               if (owner.Items.Count == 0)
+                                       return;
+                               if (vscrollbar_ctrl == null || !vscrollbar_ctrl.Visible)
+                                       return;
+
+                               int max = vscrollbar_ctrl.Maximum - page_size + 1;
+                               if (item > max)
+                                       item = max;
+                               else if (item < vscrollbar_ctrl.Minimum)
+                                       item = vscrollbar_ctrl.Minimum;
+
+                               vscrollbar_ctrl.Value = item;
+                       }
+
                        bool scrollbar_grabbed = false;
 
                        bool InScrollBar {
@@ -2632,8 +2740,18 @@ namespace System.Windows.Forms
                                        return;
                                }
 
-                               owner.SelectedIndex = index;
+                               bool is_change = owner.SelectedIndex != index;
+                               
+                               owner.SetSelectedIndex (index, true);
                                owner.OnSelectionChangeCommitted (new EventArgs ());
+                               
+                               // If the user selected the already selected item, SelectedIndex
+                               // won't fire these events, but .Net does, so we do it here
+                               if (!is_change) {
+                                       owner.OnSelectedValueChanged (EventArgs.Empty);
+                                       owner.OnSelectedIndexChanged (EventArgs.Empty);
+                               }
+                               
                                HideWindow ();
                        }
 
@@ -2650,6 +2768,10 @@ namespace System.Windows.Forms
                                HighlightedIndex = owner.SelectedIndex;
 
                                CalcListBoxArea ();
+                               // If the listbox would extend below the screen, move it above the textbox.
+                               Rectangle scrn_rect = Screen.FromControl (owner).Bounds;
+                               if (this.Location.Y + this.Height >= scrn_rect.Bottom)
+                                       this.Location = new Point (this.Location.X, this.Location.Y - (this.Height + owner.TextArea.Height));
                                Show ();
 
                                Refresh ();