Click here to Skip to main content
15,867,870 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi all,
I am currently thinking about creating a Component that should be dragged from the ToolBox to a Form/UserControl.

Once it is placed it should iterate through all controls on the Form/Usercontrol where the component was placed on and apply some formatting.

It should be able to automatically figure out its owner and then iterate the controls (best) before they are shown to appy the formatting logic (the iteration already works, so no problem here).

I already had the following:
C#
public Control OwningControl{get;set;}

to be at least able to set the control where I wanted the iteration to start but I always need to fire a function (in the Load event of the owning form) that calls the ApplyFormatting() function of the component to apply the formatting...

It would be great to drag the component to the form/UserControl and then just forget about it...
Maybe adjusting something in the Designer (for my colleagues to use it easily) and not in the code...
Is that possible?


UPDATE:
I figured out that there is a Site (ISite) property that allows interaction with the owning container.
This at least gives me the container at runtime, but I am not able to get all the controls in the container.


Update II
Ok, I made a step foreward thanks to a post I found on the net.
I added the following to get a hand on the owning control of a component, which is in my case a Form or a UserControl:
C#
        private delegate void HostingControlChangedHandler(object sender);

        private event HostingControlChangedHandler HostingControlChanged;

        private void InvokeHostingControlChanged()
        {
            HostingControlChangedHandler handler = HostingControlChanged;
            if (handler != null) handler(this);
        }

        Control hostingControl = null;

        [BrowsableAttribute(false)]
        public Control HostingControl
        {
            // Used to populate InitializeComponent at design time
            get
            {
                if ((hostingControl == null) && this.DesignMode)
                {
                    // Access designer host and obtain reference to root component
                    IDesignerHost designer =
                      this.GetService(typeof(IDesignerHost)) as IDesignerHost;
                    if (designer != null)
                    {
                        hostingControl = designer.RootComponent as Control;
                    }
                }
                return hostingControl;
            }
            set
            {
                if (!this.DesignMode)
                {
                    // Don't change hosting form at run time
                    if ((hostingControl != null) && (hostingControl != value))
                    {
                        throw new
                          InvalidOperationException
                          ("Can't set HostingForm at run time.");
                    }
                }
                hostingControl = value;
                InvokeHostingControlChanged();
            }


        }

// this is set in the constructor
void DefaultGridFormatter_HostingControlChanged(object sender)
        {
            _ultraGridDefaultFormatter.HostingControl = this.HostingControl;

            
            Form frm = this.HostingControl as Form;

            if (frm != null)
            {
                ((Form)this.HostingControl).Load += new EventHandler(DefaultGridFormatter_Load);
                return;
            }

            UserControl ctr = this.HostingControl as UserControl;
            if(ctr != null)
            {
                if(ctr.ParentForm != null)
                {
                    ctr.ParentForm.Load += new EventHandler(DefaultGridFormatter_Load);
                }
            }
        }


I am now able to grab the owning control and iterate through its child-controls to apply whatever is needed.
When I pull the component from the toolbox to my form the HostingControl is correctly set in InitializeComponent.
Unfortunately it does not work in the design-mode, only at runtime....

Am I missing something?

Is this in general a good approach or does it violates everything that is good in software engineering ;)



Any ideas/comments are kindly appreciated,

cheers
Andy
Posted
Updated 2-Jan-12 1:31am
v6
Comments
#realJSOP 27-Dec-11 8:47am    
Do ou mean that you want this control do perform this task while you're in the designer?
hoernchenmeister 27-Dec-11 8:51am    
The primary goal is that this task is performed at runtime, but if it is possible to do that at design time (I've seen that a lot from 3rd party controls) it would be a great thing ;)

1 solution

Check the Control's Parent property. It shouldn't be null because oit's set when the control is added to the form.

Probably the least hassle would be to create a public method in the form itself, and have the control call that method from its Load event. It's generally considered bad practice to have the cont5ol know about and call a method in the parent, though.

You might also be able to change the accessibility of the parent's Controls collection and process that colleciton inside your control.
 
Share this answer
 
Comments
hoernchenmeister 27-Dec-11 9:04am    
Thanks for your answer John,
thing is that I deal with a Component (component class): In my case it is a non visual component that should be dragged from the ToolBox to a Form/Usercontrol.
Thus it does not have a Parent property.
Only Container and Compnents...

My OwningControl did exactly what you mentioned. It had a setter that called the formatting logic. The setter was set by the form in its load event. But in that stage it was just a class.

<pre lang="c#">
private Control _hostingControl;
public virtual Control HostingControl
{
get { return _hostingControl; }
set
{
_hostingControl = value;
if (_hostingControl == null)
{
return;
}
Format();
}
}
</pre>


The goal now is to turn that into a non visual component that can be dragged to any form/usercontrol and formats stuff without any further action.
So my colleagues just need to drag it and thats it...

I am sorry if my question wasn't clear enough on this...

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