Click here to Skip to main content
15,849,678 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi there

I am experimenting with ExtenderProviders and run into a problem.

ExtenderProvider allows you to virtualy add properties to existing classes. My project uses Control as the base class. At DesignTime, I need a reference to Control.Parent for controls on a Form.

To illustrate, suppose you had the following trivial class ExtenderProvider (it doesn't do anything of interest except illustrate). This ExtenderProvider extends the Button class. I added two buttons to a Form, added the ExtenderProvider (which pops up on the toolbox after a previous build). The buttons have the TestString property as expected.

The issue is that, once the code goes into "EndInit", the Control.Parent of each button is still not set. InitializeComponent suggests that it should be set. And, at Run Time, it is set, but not Design Time.

Is this by design? Or am I doing something wrong?

The code forExtenderProvider, and for InitializeComponent (from my Form) is reproduced below:

C#
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections.Generic;

namespace ExtenderProviderDemo
{
    [ProvideProperty("TestString", typeof(Button))]
    public class ExtenderProvider:Component, IExtenderProvider, ISupportInitialize
    {
        Dictionary<control,> testStrings = new Dictionary<control,string>();

        public ExtenderProvider() { }

        public string GetTestString (Control extendee) {  
            if(testStrings.ContainsKey(extendee))
                return testStrings[extendee];
            else
                return string.Empty;
        
        }

        public void SetTestString(Control extendee, string testString) {
            if (testStrings.ContainsKey(extendee)) {
                testStrings[extendee] = testString;
            }

            else
                testStrings.Add(extendee, testString);
        }

        #region IExtenderProvider Members
        public bool CanExtend(object extendee)  {
            return extendee is Button;
        }
        #endregion

        #region ISupportInitialize Members

        public void BeginInit()  {
        }

        public void EndInit() {
            foreach (KeyValuePair<control,> pair in testStrings) {
                MessageBox.Show("Control " + pair.Key.Name + " : Parent null ? " + (pair.Key.Parent == null).ToString());
            } 
        }

        #endregion
    }
}

private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.extenderProvider1 = new ExtenderProviderDemo.ExtenderProvider();
            ((System.ComponentModel.ISupportInitialize)(this.extenderProvider1)).BeginInit();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(102, 80);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.extenderProvider1.SetTestString(this.button1, "");
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(115, 120);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(75, 23);
            this.button2.TabIndex = 1;
            this.extenderProvider1.SetTestString(this.button2, "Test");
            this.button2.Text = "button2";
            this.button2.UseVisualStyleBackColor = true;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)(this.extenderProvider1)).EndInit();
            this.ResumeLayout(false);

        }
Posted

You say you Inherit from Control, but I see Component.
Anyway, it shouldn't matter.
I think this might be what you are looking for[^].
I didn't write it, but it helped me a lot when creating a custom Component :)
Other than that I see a this.SuspendLayout[^] and a this.ResumeLayout[^] in the InitializeComponent. That could be a problem. Since the InitializeComponent is auto-generated it won't do much good to edit it though.
Try the link to get the parent Form.
Hope it helps, good luck!
 
Share this answer
 
Comments
Ryan Minor 6-Sep-11 8:09am    
Hi there. The solution in the link works for some reason :) I noticed DevExpress uses that same technique. Not sure why it works but thanks for the link. Cheers
Sander Rossel 6-Sep-11 12:51pm    
Actually, if you'd use a tool like Refactor or JustDecompile you'd see the exact same code in Microsoft's components :)
It's a bit of magic, but it works well ;)
Glad I could help.
Espen Harlinn 6-Sep-11 18:27pm    
Very nice links - 5'ed
Sander Rossel 7-Sep-11 2:07am    
Thanks :)
Asking just in case:

Do you know that, for example:

C#
this.Controls.Add(this.button2);


has strictly the same effect as

C#
this.button2.Parent = this;


—SA
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900