Search code examples
c#winformseventscustom-controlsdesigner

WinForms Designer Removing Events When a Control is Changed


Edit: I found the problem and posted the answer below!

I have a few custom controls in WinForms and I am getting a problem where on my Form, when I change a control in the designer (such as moving it left one pixel and then moving it back), every event that was being applied to my controls is removed from the designer code.

As an example, with my custom button I am not doing anything special to the Click event. I do not even touch that property in the class where I inherit the WinForms Button class but when any one control in my Form is changed, the buttons click event is removed.

I haven't been able to find anything related to the designer removing events online and I don't see anything in my code that would cause such a thing.

Here is code for the custom button that I have if it helps:

CustomVisualButton.cs

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;

namespace CustomVisual {

    [Designer( typeof( CustomVisualControlDesigner ) )]
    public class CustomVisualButton : Button, CustomVisualControlInterface {

        private Boolean _IsHovering = false;

        #region Properties

        [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden ), Browsable( false )]
        public override Font Font {
            get {
                return base.Font;
            }
            set {
                base.Font = value;
            }
        }

        #endregion

        #region Constructor

        public CustomVisualButton( ) {

            DoubleBuffered = true;
            Font = CustomVisualPalette.DefaultFont;
            SetStyle( ControlStyles.UserPaint, true );
            SetStyle( ControlStyles.SupportsTransparentBackColor, true );
        }

        #endregion

        #region Overrides

        protected override void OnMouseEnter( EventArgs Args ) {

            base.OnMouseEnter( Args );
            _IsHovering = true;
            Cursor = Cursors.Hand;
        }

        protected override void OnMouseLeave( EventArgs Args ) {

            base.OnMouseLeave( Args );
            _IsHovering = false;
            Cursor = Cursors.Default;
        }

        protected override void OnPaint( PaintEventArgs Args ) {
            // long paint method
        }

        protected override void OnResize( EventArgs Args ) {

            base.OnResize( Args );

            if ( CustomVisualPalette.FORCE_HEIGHT > 0 ) {

                Height = CustomVisualPalette.FORCE_HEIGHT;
            }
        }

        #endregion

    }

}

CustomVisualControlInterface.cs

namespace CustomVisual {

    public interface CustomVisualControlInterface {
    }

}

CustomVisualControlDesigner.cs

using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Drawing;
using System;

namespace CustomVisual {


    public class CustomVisualControlDesigner : ControlDesigner {

        private DesignerActionListCollection _ActionLists;

        public override DesignerActionListCollection ActionLists {
            get {
                if ( null == _ActionLists ) {
                    _ActionLists = new DesignerActionListCollection( );
                    _ActionLists.Add( new CustomVisualControlActionList( this.Component ) );
                }
                return _ActionLists;
            }
        }

    }

    public class CustomVisualControlActionList : DesignerActionList {

        private Control _Control;
        private DesignerActionUIService _Service = null;

        public CustomVisualControlInterface AlignSubject { get; set; }

        public CustomVisualControlActionList( IComponent Component )
            : base( Component ) {

            _Control = Component as Control;
            _Service = GetService( typeof( DesignerActionUIService ) ) as DesignerActionUIService;

        }

        public void RefreshDesigner( ) {

            _Service.HideUI( _Control );
            _Service.Refresh( _Control );
            _Service.ShowUI( _Control );
        }

        public Int32 SyncHeight( Control Source, Control Destination ) {
            // vertical alignment for elements of possible different height
        }

        public void MatchWidth( ) {
            // makes element width same as subject width
        }

        public void PlaceUnder( ) {
            // places element under subject
        }

        public void PlaceCloseUnder( ) {
            // places element close under subject
        }

        public void PlaceRight( ) {
            // places element right of subject
        }

        public void PlaceCloseRight( ) {
            // places element close right of subject
        }

        public void PlaceAbove( ) {
            // places element above subject
        }

        public void PlaceLeft( ) {
            // places element left of subject
        }

        public void AnchorType1( ) {
            // code to align to certain spot
        }

        public override DesignerActionItemCollection GetSortedActionItems( ) {

            DesignerActionItemCollection Items = new DesignerActionItemCollection( );
            Items.Add( new DesignerActionPropertyItem( "AlignSubject", "Subject", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "MatchWidth", "match width", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "PlaceAbove", "place above", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "PlaceRight", "place right", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "PlaceCloseRight", "place close right", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "PlaceUnder", "place under", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "PlaceCloseUnder", "place close under", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "PlaceLeft", "place left", "alignment" ) );
            Items.Add( new DesignerActionMethodItem( this, "AnchorType1", "anchor type 1", "anchors" ) );
            return Items;

        }

    }
}

Solution

  • Make sure that when you edit the designer generated code, you edit in such a way so that it can read it and re-serialize it. In this situation the designer was looking for:

    control.Click += new System.EventHandler(this.methodname)

    but I was giving it:

    control.Click += this.methodname

    and although it worked just fine, when the designer was edited and re-serialized, it couldn't parse what I had done and just removed it.

    I found my mistake by making the designer generate an event and that's when I noticed the code it made and what I was giving it were different. If you are having similar problems then I suggest getting the designer to generate something similar to what you are doing and then using that as a guideline.