Windows Develop Bookmark and Share   
 index > Windows Forms Designer > Inherited Click handler
 

Inherited Click handler

I have an MDI application in which all of the child forms inherit from a base form. This base form handles all of the common functionality of the child forms, including form initialization and closing logic. I have a protected method called CloseButton_Click which is supposed to be the Click handler for any button on a derived form which closes the form when it is clicked (primarily OK and Cancel buttons, but there a few other cases as well). The method sets the DialogResult of the form to the DialogResult of the button, and then closes the form (similar to the functionality of modal forms, but my forms are not modal). However, when I look at the events for the button in my derived form, CloseButton_Click is not an option to bind the Click event to. So I went into InitializeComponent and added the handler manually. The next time I opened the form in the designer, I got this:

The method 'CloseButton_Click' cannot be the method for an event because a class this class derives from already defines the method

Its almost like the Designer is trying to create the event handler during de-serialization, but I dont know why it would do that. Obviously I can create separate event handlers for each button and have them call the base method, but I really dont see why I should have to. Can anyone explain why this is happening?

CommonGenius.com  Tuesday, January 17, 2006 4:07 PM
Yes I hit this problem when upgrading my project from VS 2003 to 2005. I had an User Control which was inheriting from a base user control. In my derived control I wanted to use event handlers in the base class, but the designer was having none of it.
It displayed fine in VS2003, so why they felt the need to break it in VS2005 is anyones guess! I was hoping they would have fixed it so the dropdown box in the event properties included any matching base methods.

Anyway, it isn't necessary to create separate handlers... just bypass the designer, and assign the events yourself in your forms constructor.

E.g.
public class TopForm() : baseForm
{
public TopForm()

{
InitializeComponent();
this.yourButton.Click +=
new System.EventHandler(CloseButton_Click);

}
}
Gushie  Wednesday, January 25, 2006 4:23 PM
I ran into this same problem. It's quite annoying. Of course you can bypass the designer, but then you can't use the designer anymore. :(
TheKeck  Thursday, February 16, 2006 5:58 PM

Winforms designer parses intializecomponent method block at design time including the eventhandler bindings to the events to display it in the property grid.

Are you sure you did not declare another CloseButton_Click method in your child form?  I could not repro this in 1.1.

[EDIT] Ooops, did not read the next posts that this is a 2.0 issue...

joeycalisay  Thursday, February 16, 2006 11:57 PM
Yes this bug is really annoying Any info about patch?
Alex Golikov  Friday, February 17, 2006 7:38 AM
I've just wasted an hour on this bug - yes you can code the event hookups manually, but this then breaks the Designer. So I've added a test for Design mode in my control constructor, and only setup the events if its not in Design mode. Designer now works.

brian
bschaldon  Thursday, February 23, 2006 6:44 PM
Someone has submitted this as a bug in the Product Feedback Center: http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=08a84e99-97bd-4ab7-b74e-e5eb5d7dfa2e. Vote on the bug to increase its visibility to Microsoft; hopefully they will put out a patch for it.
CommonGenius.com  Thursday, February 23, 2006 7:03 PM

CommonGenius.com wrote:
Someone has submitted this as a bug in the Product Feedback Center: http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=08a84e99-97bd-4ab7-b74e-e5eb5d7dfa2e. Vote on the bug to increase its visibility to Microsoft; hopefully they will put out a patch for it.

Yea - vote for it...

Alex Golikov  Sunday, February 26, 2006 8:48 AM
Too late, MSFT changed the complaint status to "Closed (By Design)". I guess they don't understand how object oriented programming works

(Their "workaround" is to give every child object its own click handler that calls base.whatever.)
Bill van Melle  Friday, April 13, 2007 10:23 PM
Remove all inheritace event from InitializeComponent() and put your event on constructor after InitializeComponent();. I hope this trick will do
Kurniawan  Tuesday, August 21, 2007 5:03 AM
Kurniawan wrote:
Remove all inheritace event from InitializeComponent() and put your event on constructor after InitializeComponent();. I hope this trick will do

Isn't that exactly what Gushie recommended in the second post above?

It works, but doesn't play with the designer. E.g., if you double-click on a control to create or edit its default event handler (such as Click), I don't think you'll get the behavior you'd really expect from a designer that understood what was going on.
Bill van Melle  Tuesday, August 21, 2007 7:27 PM
VS2008 - just got bitten by this bug.

Very lame of microsoft not to fix this problem, as they always close these bugs 'By Design'.
rlarno  Tuesday, February 24, 2009 10:36 AM
I find the easiest work around to exposing your bases methods for events is to write a wrapper.

Delcare the method with the same name in your top class using the new keyword.

In this method call the base.MethodName with the same arguments.

Now you can link your objects events through your wrapped method to call the base method that is inherited.



EXAMPLE: Wrapping the ContentsResized event to a base class method to automatically re-size RichTextBox controls.


This is the base class that inherits a Form control. Copy this code and paste it into a new class file.


using System.Drawing;
using System.Windows.Forms;

namespace PcSanity.Interfaces { public class ActionReportDialog : Form { protected int WidestControl; protected void ResizeRichTextBox(object sender, ContentsResizedEventArgs e) { Control ControlToResize = (Control)sender; ControlToResize.Width = e.NewRectangle.Width; // used to process dialog width if (ControlToResize.Right > WidestControl) WidestControl = ControlToResize.Right; } } }




Next you need to create a new Form within your project.

Now View Code to show the Forms class. You should have something like this.




using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PcSanity
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}





Now you have update the inheritance of the form to inherit the base class we made earlier.

The result is something like this.




    public partial class Form1 : PcSanity.Interfaces.ActionReportDialog



{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{

}
}




Now you need to add a copy of the event handler method declaring it with the new keyword and then make it call the base class.





    public partial class Form1 : PcSanity.Interfaces.ActionReportDialog
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{

}

protected void ResizeRichTextBox(object sender, ContentsResizedEventArgs e)
{
base.ResizeRichTextBox(sender, e);
}

}





Add some RichTextBox controls to this Form.

Select all the RichTextBox controls you added and view the properties.

Set multiline to each control to false.

Goto the Events pane.

Browse and find 'ContentsResized'

Click the drop down arrow and click to add the event wrapper you added to the top level class.

Now if you add some code to write text to the RichTextBox controls you added the will resize on the form automatically and you have access to widest control to resize the Form if required =]




    public partial class Form1 : PcSanity.Interfaces.ActionReportDialog
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
richTextBox1.Text = "short text";
richTextBox2.Text = "Alot more text... dsgsfdgihsdighdishgishdighsihgihsighids";
richTextBox3.Text = "Alot more text... dsgsfdgihsdighdishgishdigsdghdsgdsgsdgdsgsdgdsgdsgsdgdsgsdgsdhsihgihsighids";
this.Width = base.WidestControl + 15;

}

protected void ResizeRichTextBox(object sender, ContentsResizedEventArgs e)
{
base.ResizeRichTextBox(sender, e);
}
}




Now if you show this dialog. The load event will reset the text of all the RichTextBox controls you added.

After you set the text the RichTextBox control will fire ResizeRichTextBox method. Which in turn fires the base method.

The base method will resize the RichTextBox control based of the size of it's own contents and reset the WidestControl value if it is bigger.

The last thing we do is reset the Width property for the Form control to the widest controls RichTextBox controls calculated right + 15.

Boom

Spiral Galaxy  Tuesday, September 15, 2009 4:05 AM

You can use google to search for other answers

Custom Search

More Threads

• Adding controls to a custom control using the designer
• Alter GridSize for DesignSurface
• User Control Property of Point Array
• Creating an Editor
• designer not showing localized exceptionmessages
• Drawing on textbox using SetpixelV
• Visual studio 2008 designer error.
• Clone Copy a Panel with its controls
• e.cancel=true
• Having problems with IDesignerHost with Global selecting.