Hi all,

Since I'm new here, let me introduce myself. I'm Tim and I'm working on a custom forms designer based on framework 2.0.

So far the new framework has been making this project a lot easier than if I still had to use 1.1, but now I ran into some weird behavior. Not that it is lethal to my application, but I thought let's just discuss it here and if we all agree it must be a bug report it with MS.

On my main form I'm hosting a DesignSurface and a PropertyGrid. The PropertyGrid is configured to show all properties of the selected component(s) on the DesignSurface. When a component is changed on the DesignSurface (f.i. resized), the corresponding property in the PropertyGrid should be updated simultaneously. In order to achieve this, I handle the IComponentChangeService.ComponentChanged event and refresh the PropertyGrid. This approach works perfectly fine... except for one scenario (as far as I can see now): in every resize operation you'll notice the PropertyGrid is refreshed twice. The first time after you resized the first few pixels (while still dragging!) and the second time, as desired, after the mousebutton is released and the resize is done.

It's this first refresh (caused by a ComponentChanged event that is raised by the control that is in a resize operation) I'm interested in. The Visual Studio 2005 forms designer does not show similar behavior, neither do forms designers (both VS and custom) in framework 1.1. Since the event is coming from the inner circles of the DesignSurface, I have strong suspicions that we're dealing with a bug here. It would definitely not be the first bug in the 2.0 design libraries.

Below I'll give the code that reproduces the behavior. Set a breakpoint on Me.PropertyGrid1.Refresh() to observe the undesired event.

Public Class Form1

    Private _surface As DesignSurface
    Private _host As IDesignerHost
    Private _root As Control
    Private WithEvents _selection As ISelectionService
    Private WithEvents _change As IComponentChangeService

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me._surface = New DesignSurface(GetType(Form))
        Me._host = CType(Me._surface.GetService(GetType(IDesignerHost)), IDesignerHost)
        Me._root = CType(Me._host.RootComponent, Control)
        Me._selection = CType(Me._surface.GetService(GetType(ISelectionService)), ISelectionService)
        Me._change = CType(Me._surface.GetService(GetType(IComponentChangeService)), IComponentChangeService)
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim bto As Button = CType(Me._host.CreateComponent(GetType(Button)), Button)
        bto.Text = "Replace Me!"
        Me._root.Controls.Add(bto)

        Me.OnSelectionChanged(Me._selection.GetSelectedComponents)

        Dim view As Control = CType(Me._surface.View, Control)
        view.Dock = DockStyle.Fill
        Me.SplitContainer1.Panel1.Controls.Add(view)

        Me._host.Activate()
    End Sub

    Private Sub _selection_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _selection.SelectionChanged
        Me.OnSelectionChanged(Me._selection.GetSelectedComponents)
    End Sub

    Protected Overridable Sub OnSelectionChanged(ByVal newSelection As ICollection)
        Dim s(newSelection.Count - 1) As Object
        newSelection.CopyTo(s, 0)
        Me.PropertyGrid1.SelectedObjects = s
    End Sub

    Private Sub _change_ComponentChanged(ByVal sender As Object, ByVal e As System.ComponentModel.Design.ComponentChangedEventArgs) Handles _change.ComponentChanged
        Me.PropertyGrid1.Refresh()
    End Sub

End Class

Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
     _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing AndAlso components IsNot Nothing Then
            components.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
     _
    Private Sub InitializeComponent()
        Me.SplitContainer1 = New System.Windows.Forms.SplitContainer
        Me.PropertyGrid1 = New System.Windows.Forms.PropertyGrid
        Me.SplitContainer1.Panel2.SuspendLayout()
        Me.SplitContainer1.SuspendLayout()
        Me.SuspendLayout()
        '
        'SplitContainer1
        '
        Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.SplitContainer1.Location = New System.Drawing.Point(0, 0)
        Me.SplitContainer1.Name = "SplitContainer1"
        '
        'SplitContainer1.Panel1
        '
        Me.SplitContainer1.Panel1.BackColor = System.Drawing.SystemColors.Window
        '
        'SplitContainer1.Panel2
        '
        Me.SplitContainer1.Panel2.Controls.Add(Me.PropertyGrid1)
        Me.SplitContainer1.Size = New System.Drawing.Size(614, 405)
        Me.SplitContainer1.SplitterDistance = 436
        Me.SplitContainer1.TabIndex = 0
        '
        'PropertyGrid1
        '
        Me.PropertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.PropertyGrid1.Location = New System.Drawing.Point(0, 0)
        Me.PropertyGrid1.Name = "PropertyGrid1"
        Me.PropertyGrid1.Size = New System.Drawing.Size(174, 405)
        Me.PropertyGrid1.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(614, 405)
        Me.Controls.Add(Me.SplitContainer1)
        Me.Name = "Form1"
        Me.Text = "My First Custom Designer"
        Me.SplitContainer1.Panel2.ResumeLayout(False)
        Me.SplitContainer1.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub
    Friend WithEvents SplitContainer1 As System.Windows.Forms.SplitContainer
    Friend WithEvents PropertyGrid1 As System.Windows.Forms.PropertyGrid

End Class