2008-02-19 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / PropertyGridView.cs
index adaf4b2262c4c71acf989739dec8d78e620708c3..6966ef0a43536b82ca2e63e56be803fd9546388b 100644 (file)
@@ -52,13 +52,12 @@ namespace System.Windows.Forms.PropertyGridInternal {
                private PropertyGridTextBox grid_textbox;
                private PropertyGrid property_grid;
                private bool resizing_grid;
-               private int open_grid_item_count = -1;
-               private int skipped_grid_items;
                private PropertyGridDropDown dropdown_form;
                private Form dialog_form;
                private ImplicitVScrollBar vbar;
                private StringFormat string_format;
                private Font bold_font;
+               private Brush inactive_text_brush;
                #endregion
 
                #region Contructors
@@ -83,19 +82,19 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        dialog_form.FormBorderStyle = FormBorderStyle.None;
                        dialog_form.ShowInTaskbar = false;
 
-                       skipped_grid_items = 0;
                        row_height = Font.Height + font_height_padding;
 
                        grid_textbox.Visible = false;
                        grid_textbox.Font = this.Font;
                        grid_textbox.BackColor = SystemColors.Window;
                        // Not working at all, used to??
-                       grid_textbox.Validating += new CancelEventHandler (TextBoxValidating);
+                       // grid_textbox.Validating += new CancelEventHandler (TextBoxValidating);
                        grid_textbox.ToggleValue+=new EventHandler (grid_textbox_ToggleValue);
                        this.Controls.Add (grid_textbox);
 
                        vbar = new ImplicitVScrollBar ();
                        vbar.Visible = false;
+                       vbar.Value = 0;
                        vbar.ValueChanged+=new EventHandler (VScrollBar_HandleValueChanged);
                        vbar.Dock = DockStyle.Right;
                        this.Controls.AddImplicit (vbar);
@@ -103,6 +102,7 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        resizing_grid = false;
 
                        bold_font = new Font (this.Font, FontStyle.Bold);
+                       inactive_text_brush = new SolidBrush (ThemeEngine.Current.ColorGrayText);
 
                        ForeColorChanged+=new EventHandler (RedrawEvent);
                        BackColorChanged+=new System.EventHandler (RedrawEvent);
@@ -133,6 +133,9 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                private void InvalidateItem (GridEntry item)
                {
+                       if (item == null)
+                               return;
+
                        Rectangle rect = new Rectangle (0, item.Top, Width, row_height);
                        Invalidate (rect);
 
@@ -151,10 +154,8 @@ namespace System.Windows.Forms.PropertyGridInternal {
                                ToggleValue ((GridEntry)property_grid.SelectedGridItem);
                }
 
-               protected override void OnPaint (PaintEventArgs e) {
-                       // Decide if we need a scrollbar
-                       open_grid_item_count = 0;
-
+               protected override void OnPaint (PaintEventArgs e) 
+               {
                        // Background
                        e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), ClientRectangle);
                        
@@ -170,7 +171,7 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        if (vbar == null || !vbar.Visible)
                                return;
                        if (e.Delta < 0)
-                               vbar.Value = Math.Min (vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum);
+                               vbar.Value = Math.Min (vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum - vbar.SmallChange);
                        else
                                vbar.Value = Math.Max (0, vbar.Value - SystemInformation.MouseWheelScrollLines);
                        base.OnMouseWheel (e);
@@ -194,9 +195,15 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                protected override void OnMouseDown (MouseEventArgs e) 
                {
+                       base.OnMouseDown (e);
                        if (property_grid.RootGridItem == null)
                                return;
 
+                       if (!TrySetEntry ((GridEntry)property_grid.SelectedGridItem, grid_textbox.Text)) {
+                               FocusSelection ();
+                               return;
+                       }
+
                        if (e.X > SplitterLocation - RESIZE_WIDTH && e.X < SplitterLocation + RESIZE_WIDTH) {
                                resizing_grid = true;
                        }
@@ -206,14 +213,14 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                                if (foundItem != null) {
                                        if (foundItem.Expandable && ((GridEntry)foundItem).PlusMinusBounds.Contains (e.X, e.Y))
-                                                       foundItem.Expanded = !foundItem.Expanded;
-
+                                               foundItem.Expanded = !foundItem.Expanded;
+                                       
                                        this.property_grid.SelectedGridItem = foundItem;
-                                       if (!GridLabelHitTest (e.X))
-                                               FocusSelection ();
+                                       if (!GridLabelHitTest (e.X)) {
+                                               // send mouse down so we get the carret under cursor
+                                               grid_textbox.SendMouseDown (PointToScreen (e.Location));
+                                       }
                                }
-                               
-                               base.OnMouseDown (e);
                        }
                }
 
@@ -225,13 +232,11 @@ namespace System.Windows.Forms.PropertyGridInternal {
                protected override void OnResize (EventArgs e) {
                        base.OnResize (e);
                        if (property_grid.SelectedGridItem != null) { // initialized already
-                               SuspendLayout ();
                                UpdateView ();
                                // MS scrolls to the currently selected item on resize, even
                                // when it's not in the visible area.
                                // 
-                               EnsureItemIsVisible ((GridEntry)property_grid.SelectedGridItem);
-                               ResumeLayout (false);
+                               ScrollToItem ((GridEntry)property_grid.SelectedGridItem);
                        }
                }
 
@@ -251,12 +256,12 @@ namespace System.Windows.Forms.PropertyGridInternal {
                            && grid_textbox.Visible) {
                                switch (keyData) {
                                case Keys.Enter:
-                                       selectedItem.SetValue (grid_textbox.Text);
-                                       UnfocusSelection ();
+                                       if (TrySetEntry (selectedItem, grid_textbox.Text))
+                                               UnfocusSelection ();
                                        return true;
                                case Keys.Escape:
                                        if (selectedItem.IsEditable)
-                                               grid_textbox.Text = selectedItem.ValueString;
+                                               UpdateItem (selectedItem); // reset value
                                        UnfocusSelection ();
                                        return true;
                                case Keys.Tab:
@@ -269,6 +274,25 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        return base.ProcessDialogKey (keyData);
                }
 
+               private bool TrySetEntry (GridEntry entry, object value)
+               {
+                       if (entry == null || grid_textbox.Text.Equals (entry.ValueText))
+                               return true;
+
+                       if (entry.IsEditable || !entry.IsEditable && (entry.HasCustomEditor || entry.AcceptedValues != null) ||
+                           !entry.IsMerged || entry.HasMergedValue || 
+                           (!entry.HasMergedValue && grid_textbox.Text != String.Empty)) {
+                               string error = null;
+                               bool changed = entry.SetValue (value, out error);
+                               if (!changed && error != null) {
+                                       if (property_grid.ShowError (error, MessageBoxButtons.OKCancel) == DialogResult.Cancel)
+                                               UpdateItem (entry); // restore value, repaint, etc
+                                       else
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
 
                protected override bool IsInputKey (Keys keyData) {
                        switch (keyData) {
@@ -357,7 +381,8 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        return item;
                }
 
-               protected override void OnKeyDown (KeyEventArgs e) {
+               protected override void OnKeyDown (KeyEventArgs e) 
+               {
                        GridEntry selectedItem = (GridEntry)property_grid.SelectedGridItem;
 
                        if (selectedItem == null) {
@@ -366,6 +391,11 @@ namespace System.Windows.Forms.PropertyGridInternal {
                                return;
                        }
 
+                       if (!TrySetEntry (selectedItem, grid_textbox.Text)) {
+                               FocusSelection ();
+                               return;
+                       }
+
                        switch (e.KeyData & Keys.KeyCode) {
                        case Keys.Left:
                                if (e.Control) {
@@ -449,7 +479,7 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                #region Private Helper Methods
 
-               private int SplitterLocation{
+               private int SplitterLocation {
                        get {
                                return (int)(splitter_percent*Width);
                        }
@@ -494,21 +524,56 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        return null;
                }
 
-               private void UpdateScrollBar () {
-                       int visible_rows = this.ClientRectangle.Height/row_height;
-                       if (open_grid_item_count > visible_rows) {
+               private int GetVisibleItemsCount (GridEntry entry)
+               {
+                       if (entry == null)
+                               return 0;
+
+                       int count = 0;
+                       foreach (GridEntry e in entry.GridItems) {
+                               count += 1;
+                               if (e.Expandable && e.Expanded)
+                                       count += GetVisibleItemsCount (e);
+                       }
+                       return count;
+               }
+
+               private int GetVisibleRowsCount ()
+               {
+                       return this.Height / row_height;
+               }
+
+               private void UpdateScrollBar ()
+               {
+                       if (property_grid.RootGridItem == null)
+                               return;
+
+                       int visibleRows = GetVisibleRowsCount ();
+                       int openedItems = GetVisibleItemsCount ((GridEntry)property_grid.RootGridItem);
+                       if (openedItems > visibleRows) {
                                vbar.Visible = true;
                                vbar.SmallChange = 1;
                                vbar.Minimum = 0;
-                               vbar.Maximum = open_grid_item_count-1;
-                               vbar.LargeChange = visible_rows;
-                       }
-                       else {
+                               vbar.Maximum = openedItems - 1;
+                               vbar.LargeChange = visibleRows;
+                       } else {
+                               vbar.Value = 0;
                                vbar.Visible = false;
                        }
-
+                       UpdateGridTextBoxBounds ((GridEntry)property_grid.SelectedGridItem);
                }
 
+               // private bool GetScrollBarVisible ()
+               // {
+               //      if (property_grid.RootGridItem == null)
+               //              return false;
+                // 
+               //      int visibleRows = GetVisibleRowsCount ();
+               //      int openedItems = GetVisibleItemsCount ((GridEntry)property_grid.RootGridItem);
+               //      if (openedItems > visibleRows)
+               //              return true;
+               //      return false;
+               // }
                #region Drawing Code
 
                private void DrawGridItems (GridItemCollection grid_items, PaintEventArgs pevent, int depth, ref int yLoc) {
@@ -525,7 +590,7 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                        if (grid_item.GridItemType == GridItemType.Category) {
                                font = bold_font;
-                               brush = SystemBrushes.ControlDark;
+                               brush = SystemBrushes.ControlText;
 
                                pevent.Graphics.DrawString (grid_item.Label, font, brush, rect.X + 1, rect.Y + ENTRY_SPACING);
                                if (grid_item == property_grid.SelectedGridItem) {
@@ -545,13 +610,9 @@ namespace System.Windows.Forms.PropertyGridInternal {
                                        brush = SystemBrushes.HighlightText;
                                }
                                else {
-                                       brush = SystemBrushes.WindowText;
-                                       if (grid_item.PropertyDescriptor.IsReadOnly
-                                           && !grid_item.Expandable)
-                                               brush = SystemBrushes.InactiveCaption;
+                                       brush = grid_item.IsReadOnly ? inactive_text_brush : SystemBrushes.ControlText;
                                }
                        }
-
                        pevent.Graphics.DrawString (grid_item.Label, font, brush,
                                                    new Rectangle (rect.X + 1, rect.Y + ENTRY_SPACING, rect.Width - ENTRY_SPACING, rect.Height - ENTRY_SPACING),
                                                    string_format);
@@ -562,24 +623,27 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        if (grid_item.PropertyDescriptor == null)
                                return; 
 
-                       int xLoc = SplitterLocation+1;
+                       int xLoc = SplitterLocation+ENTRY_SPACING;
                        if (grid_item.PaintValueSupported) {
                                pevent.Graphics.DrawRectangle (Pens.Black, SplitterLocation + ENTRY_SPACING, 
                                                               rect.Y + 2, VALUE_PAINT_WIDTH + 1, row_height - ENTRY_SPACING*2);
                                grid_item.PaintValue (pevent.Graphics, 
                                                      new Rectangle (SplitterLocation + ENTRY_SPACING + 1, 
                                                                     rect.Y + ENTRY_SPACING + 1,
-                                                                    VALUE_PAINT_WIDTH, row_height - (ENTRY_SPACING*2 + 1)));
+                                                                    VALUE_PAINT_WIDTH, row_height - (ENTRY_SPACING*2 +1)));
                                xLoc += VALUE_PAINT_INDENT;
                        }
 
                        Font font = this.Font;
-                       if (grid_item.IsResetable)
+                       if (grid_item.IsResetable || !grid_item.HasDefaultValue)
                                font = bold_font;
-                       pevent.Graphics.DrawString (grid_item.ValueString, font,
-                                                   SystemBrushes.WindowText,
-                                                   new RectangleF (xLoc, rect.Y + ENTRY_SPACING,
-                                                                   ClientRectangle.Width-(xLoc), row_height),string_format);
+                       Brush brush = grid_item.IsReadOnly ? inactive_text_brush : SystemBrushes.ControlText;
+                       string valueText = grid_item.IsMerged && !grid_item.HasMergedValue ? String.Empty : grid_item.ValueText;
+                       pevent.Graphics.DrawString (valueText, font,
+                                                   brush,
+                                                   new RectangleF (xLoc + ENTRY_SPACING, rect.Y + ENTRY_SPACING,
+                                                                   ClientRectangle.Width-(xLoc), row_height - ENTRY_SPACING*2), 
+                                                   string_format);
                }
 
                private void DrawGridItem (GridEntry grid_item, PaintEventArgs pevent, int depth, ref int yLoc) {
@@ -619,7 +683,6 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        }
                        grid_item.Top = yLoc;
                        yLoc += row_height;
-                       open_grid_item_count++;
                }
 
                private Rectangle DrawPlusMinus (Graphics g, int x, int y, bool expanded, bool category) {
@@ -642,11 +705,12 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        Refresh ();
                }
 
-               private void TextBoxValidating (object sender, CancelEventArgs e) 
-               {
-                       if (this.property_grid.SelectedGridItem != null)
-                               ((GridEntry) property_grid.SelectedGridItem).SetValue (grid_textbox.Text);
-               }
+               // private void TextBoxValidating (object sender, CancelEventArgs e)
+               // {
+               //      GridEntry entry = (GridEntry) property_grid.SelectedGridItem;
+               //      if (entry != null && entry.IsEditable)
+               //              TrySetEntry (entry, grid_textbox.Text);
+               // }
 
                #endregion
 
@@ -669,8 +733,11 @@ namespace System.Windows.Forms.PropertyGridInternal {
                void AcceptListBoxSelection (object sender) 
                {
                        GridEntry entry = this.property_grid.SelectedGridItem as GridEntry;
-                       if (entry != null)
-                               entry.SetValue ((string) ((ListBox) sender).SelectedItem);
+                       if (entry != null) {
+                               grid_textbox.Text = (string) ((ListBox) sender).SelectedItem;
+                               if (TrySetEntry (entry, (string) ((ListBox) sender).SelectedItem))
+                                       UnfocusSelection ();
+                       }
                        CloseDropDown ();
                }
 
@@ -695,11 +762,12 @@ namespace System.Windows.Forms.PropertyGridInternal {
                                                int i = 0;
                                                foreach (object obj in std_values) {
                                                        listBox.Items.Add (obj);
-                                                       if (entry.ValueString != null && entry.ValueString.Equals (obj))
+                                                       if (entry.ValueText != null && entry.ValueText.Equals (obj))
                                                                selected_index = i;
                                                        i++;
                                                }
                                                listBox.Height = row_height * Math.Min (listBox.Items.Count, 15);
+                                               listBox.Width = ClientRectangle.Width - SplitterLocation - (vbar.Visible ? vbar.Width : 0);
                                                listBox.KeyDown += new KeyEventHandler (listBox_KeyDown);
                                                listBox.MouseUp+=new MouseEventHandler (listBox_MouseUp);
                                                if (std_values.Count > 0)
@@ -719,18 +787,6 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                private void VScrollBar_HandleValueChanged (object sender, EventArgs e) 
                {
-                       if (vbar.Value <= 0)
-                               vbar.Value = 0;
-                       if (vbar.Value > vbar.Maximum-ClientRectangle.Height/row_height)
-                               vbar.Value = vbar.Maximum-ClientRectangle.Height/row_height+1;
-
-                       int scroll_amount = (skipped_grid_items-vbar.Value)*row_height;
-
-                       if (scroll_amount == 0)
-                               return;
-
-                       skipped_grid_items = vbar.Value;
-                       XplatUI.ScrollWindow (Handle, 0, scroll_amount, false);
                        UpdateView ();
                }
 
@@ -747,31 +803,35 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                internal void UpdateItem (GridEntry entry)
                {
-                       if (entry == null || entry.GridItemType != GridItemType.Property) {
+                       if (entry == null || entry.GridItemType == GridItemType.Category || 
+                           entry.GridItemType == GridItemType.Root) {
                                grid_textbox.Visible = false;
+                               InvalidateItem (entry);
                                return;
                        }
 
                        if (property_grid.SelectedGridItem == entry) {
                                SuspendLayout ();
                                grid_textbox.Visible = false;
-                               if (entry.IsResetable)
+                               if (entry.IsResetable || !entry.HasDefaultValue)
                                        grid_textbox.Font = bold_font;
                                else
                                        grid_textbox.Font = this.Font;
-       
-                               grid_textbox.DropDownButtonVisible = entry.AcceptedValues != null || 
-                                       entry.EditorStyle == UITypeEditorEditStyle.DropDown;
-                               grid_textbox.DialogButtonVisible = entry.EditorStyle == UITypeEditorEditStyle.Modal;
-                               grid_textbox.ReadOnly = !entry.IsEditable;
-
-                               int y = -vbar.Value*row_height;
-                               CalculateItemY (entry, property_grid.RootGridItem.GridItems, ref y);
-                               int x = SplitterLocation + 1 + (entry.PaintValueSupported ? 27 : 0);
-                               grid_textbox.SetBounds (x, y + ENTRY_SPACING,
-                                                       ClientRectangle.Width - x - (vbar.Visible ? vbar.Width : 0),
-                                                       row_height - ENTRY_SPACING);
-                               grid_textbox.Text = entry.ValueString != null ? entry.ValueString : "";
+
+                               if (entry.IsReadOnly) {
+                                       grid_textbox.DropDownButtonVisible = false;
+                                       grid_textbox.DialogButtonVisible = false;
+                                       grid_textbox.ReadOnly = true;
+                                       grid_textbox.ForeColor = SystemColors.GrayText;
+                               } else {
+                                       grid_textbox.DropDownButtonVisible = entry.AcceptedValues != null || 
+                                               entry.EditorStyle == UITypeEditorEditStyle.DropDown;
+                                       grid_textbox.DialogButtonVisible = entry.EditorStyle == UITypeEditorEditStyle.Modal;
+                                       grid_textbox.ForeColor = SystemColors.ControlText;
+                                       grid_textbox.ReadOnly = !entry.IsEditable;
+                               }
+                               UpdateGridTextBoxBounds (entry);
+                               grid_textbox.Text = entry.IsMerged && !entry.HasMergedValue ? String.Empty : entry.ValueText;
                                grid_textbox.Visible = true;
                                InvalidateItem (entry);
                                ResumeLayout (false);
@@ -780,6 +840,16 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        }
                }
 
+               private void UpdateGridTextBoxBounds (GridEntry entry)
+               {
+                       int y = -vbar.Value*row_height;
+                       CalculateItemY (entry, property_grid.RootGridItem.GridItems, ref y);
+                       int x = SplitterLocation + ENTRY_SPACING + (entry.PaintValueSupported ? VALUE_PAINT_INDENT : 0);
+                       grid_textbox.SetBounds (x + ENTRY_SPACING, y + ENTRY_SPACING,
+                                               ClientRectangle.Width - ENTRY_SPACING - x - (vbar.Visible ? vbar.Width : 0),
+                                               row_height - ENTRY_SPACING);
+               }
+
                // Calculates the sum of the heights of all items before the one
                //
                private bool CalculateItemY (GridEntry entry, GridItemCollection items, ref int y)
@@ -795,32 +865,36 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        return false;
                }
 
-               private void EnsureItemIsVisible (GridEntry item)
+               private void ScrollToItem (GridEntry item)
                {
                        if (item == null)
                                return;
 
                        int itemY = -vbar.Value*row_height;
+                       int value = vbar.Value;;
                        CalculateItemY (item, property_grid.RootGridItem.GridItems, ref itemY);
                        if (itemY < 0) // the new item is above the viewable area
-                               vbar.Value += itemY / row_height;
+                               value += itemY / row_height;
                        else if (itemY + row_height > Height) // the new item is below the viewable area
-                               vbar.Value += ((itemY + row_height) - Height) / row_height + 1;
+                               value += ((itemY + row_height) - Height) / row_height + 1;
+                       if (value >= vbar.Minimum && value <= vbar.Maximum)
+                               vbar.Value = value;
                }
 
-               internal void SelectItem (GridItem oldItem, GridItem newItem) 
+               internal void SelectItem (GridEntry oldItem, GridEntry newItem) 
                {
                        if (oldItem != null)
-                               InvalidateItemLabel ((GridEntry)oldItem);
+                               InvalidateItemLabel (oldItem);
                        if (newItem != null) {
-                               UpdateItem ((GridEntry) newItem);
-                               EnsureItemIsVisible ((GridEntry) newItem);
+                               UpdateItem (newItem);
+                               ScrollToItem (newItem);
                        } else
                                grid_textbox.Visible = false;
                }
 
                internal void UpdateView ()
                {
+                       UpdateScrollBar ();
                        UpdateItem ((GridEntry)property_grid.SelectedGridItem);
                        Invalidate ();
                        Update ();
@@ -828,15 +902,18 @@ namespace System.Windows.Forms.PropertyGridInternal {
 
                internal void ExpandItem (GridEntry item)
                {
+                       UpdateItem ((GridEntry)property_grid.SelectedGridItem);
                        Invalidate (new Rectangle (0, item.Top, Width, Height - item.Top));
                }
 
                internal void CollapseItem (GridEntry item)
                {
+                       UpdateItem ((GridEntry)property_grid.SelectedGridItem);
                        Invalidate (new Rectangle (0, item.Top, Width, Height - item.Top));
                }
 
-               private void ShowDropDownControl (Control control, bool block) {
+               private void ShowDropDownControl (Control control, bool block) 
+               {
                        Object  queue_id;
 
                        Form owner = FindForm ();
@@ -844,13 +921,13 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        Point location;
                        dropdown_form.Size = control.Size;
                        control.Dock = DockStyle.Fill;
-                       dropdown_form.Controls.Clear ();
                        dropdown_form.Controls.Add (control);
-                       dropdown_form.Location = PointToScreen (new Point (SplitterLocation, grid_textbox.Location.Y + row_height));
+                       dropdown_form.Width = Math.Max (ClientRectangle.Width - SplitterLocation - (vbar.Visible ? vbar.Width : 0), 
+                                                       control.Width);
+                       dropdown_form.Location = PointToScreen (new Point (grid_textbox.Right - control.Width, grid_textbox.Location.Y + row_height));
+                       RepositionInScreenWorkingArea (dropdown_form);
                        location = dropdown_form.Location;
 
-                       dropdown_form.Width = ClientRectangle.Width - SplitterLocation - (vbar.Visible ? vbar.Width : 0);
-
                        owner.AddOwnedForm (dropdown_form);
 
                        dropdown_form.Show ();
@@ -885,6 +962,26 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        }
                }
 
+               private void RepositionInScreenWorkingArea (Form form)
+               {
+                       Rectangle workingArea = Screen.FromControl (form).WorkingArea;
+                       if (!workingArea.Contains (form.Bounds)) {
+                               int x, y;
+                               x = form.Location.X;
+                               y = form.Location.Y;
+
+                               if (form.Location.X < workingArea.X)
+                                       x = workingArea.X;
+
+                               if (form.Location.Y + form.Size.Height > workingArea.Height) {
+                                       Point aboveTextBox = PointToScreen (new Point (grid_textbox.Right - form.Width, grid_textbox.Location.Y));
+                                       y = aboveTextBox.Y - form.Size.Height;
+                               }
+
+                               form.Location = new Point (x, y);
+                       }
+               }
+
                private bool HwndInControl (Control c, IntPtr hwnd)
                {
                        if (hwnd == c.window.Handle)
@@ -903,6 +1000,7 @@ namespace System.Windows.Forms.PropertyGridInternal {
                        Control c = dropdown_form.Controls[0];
                        c.Capture = false;
                        dropdown_form.Hide ();
+                       dropdown_form.Controls.Clear ();
                }
 
                public void DropDownControl (Control control) {