2
votes

I'm working in winforms, and I'm attempting to link in some events any time a form\component\usercontrol is shown in the designer, i'm trying to link in some static events that load preferences from the app.config file.

Is it possible for me to define code in my project that says "any time a control is loaded, execute this event?"

edit this is strictly a design time thing.

I have a base form, in DLL "A". That has a ton of properties, "ColorLocation, SizeLocation", and things of that nature.

In DLL "B" I have a derived form. When B is loaded into the designer, I had iEditorComponents (dont remember the exact name), that allows the user to select ColorLocation from a huge list of items specified in the app.config settings file for the current project.

The problem is, the editing component is in Dll "A", which is the base, and it doesn't have access to the app.config in "B".

I need someway to tell the editing component to "hey, use this list of strings to populate your editing control". The designer is doing everything in its power it seems to not want to execute any code in the derived classes.

2
This doesn't sound good. Design time is a world away from run time. For one, there's no good way to access a project's app.config file. For another, the odds there is anybody around to listen to the event should be zero.Hans Passant
Can you explain a bit your use case ? Do you mean you want to execute some code in your component when the containing form is loaded ?Luc Morin
Also, is this a Design Time or Run Time thing ?Luc Morin
I added quite a bit in the edit above explaining.greggorob64

2 Answers

3
votes

Yes, it's possible, but make sure what you're doing, because sounds strange.

Use the following code in your Form's or Control's constructor:

    public void Form1()
    {
       InitializeComponent();

       if (IsInWinFormsDesignMode())
       {
           // your code stuff here
       }
    }

    public static bool IsInWinFormsDesignMode()
    {
        bool returnValue = false;

        #if DEBUG  

        if ( System.ComponentModel.LicenseManager.UsageMode == 
             System.ComponentModel.LicenseUsageMode.Designtime )
        {
            returnValue = true;
        }

        #endif

        return returnValue;
    }

Hope it helps.

1
votes

I don't know if this will apply to your specific use case, but at some point in time I needed to interact with a Component's container (ie the Form), so I ended up "stealing" code from the ErrorProvider:

//code goes in your Component/Control

 private ContainerControl _containerControl = null;

 //Will contain a reference to the Form hosting this Component
        public ContainerControl ContainerControl
        {
            get { return _containerControl; }
            set { _containerControl = value; 
                 //In here setup what you need from the Form
                 //for example add a handler
                }
        }

        //Allows the VS.NET designer to set the ContainerControl
        //in the designer code. Stolen from ErrorProvider.
        public override ISite Site
        {
            set
            {
                base.Site = value;
                if (value != null)
                {
                    IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
                    if (host != null)
                    {
                        IComponent rootComponent = host.RootComponent;
                        if (rootComponent is ContainerControl)
                        {
                            this.ContainerControl = (ContainerControl)rootComponent;
                        }
                    }
                }
            }
        }

I also used a StringConverter derived class to interact with external resources from the Designer:

public class OpcDotNetTagConverter : StringConverter
    {
        #region Make It A ComboBox
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return false;
        }
        #endregion

        #region Display Tags In List
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            if ((context == null) || (context.Container == null))
            {
                return null;
            }

            Object[] Tags = this.GetTagsFromServer(context);
            if (Tags != null)
            {
                return new StandardValuesCollection(Tags);
            }
            return null;
        }

        private object[] GetTagsFromServer(ITypeDescriptorContext context)
        {
            List<string> availableTags = new List<string>();

            if (context.Instance == null)
            {
                availableTags.Add("ITypeDescriptorContext.Instance is null");
                return availableTags.ToArray();
            }


            Interfaces.IOpcDotNetServerEnabled inst = context.Instance as Interfaces.IOpcDotNetServerEnabled;
            if (inst == null)
            {
                availableTags.Add(context.Instance.ToString());
                return availableTags.ToArray();
            }

            if (inst.OpcDotNetServer == null)
            {
                availableTags.Add("No server selected");
                return availableTags.ToArray();
            }

            availableTags = inst.OpcDotNetServer.GetTagList(string.Empty);
            availableTags.Sort(Comparer<string>.Default);
            return availableTags.ToArray();
        }

        #endregion

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if(sourceType == typeof(string))
                return true;
            return base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
                return value.ToString();
            return base.ConvertFrom(context, culture, value);
        }

    }

I hope this can be of some help.

Cheers