views:

108

answers:

1

I have a component that is in conflict with another component that handles some internal translations.

What happens is that business logic components gets executed, then the translation system executes, which picks up texts now present in the form, and attempts to translate them.

The problem is that the text now contains things like numbers, dates, database-related text, etc. but before the business logic was executed, those controls was either blank or contained dummy-text prepared for translation.

I'm wondering how I can have a component that I drop on a form execute its code at a specific time in the lifetime of the form.

For instance, if I remove the offending code from the business logic component, so that it doesn't do anything upon construction, then translation work, and if I then call the method I moved that code to from Form_Load, that too works nicely.

So I'm wondering, is there a way for me, from a component (ie. descended from Component, not a visual control), to execute code just before or after Form_Load, or at least after all other components and controls have been set up?

It doesn't appear to be any link from within the component back to the form, so for me to hook into the Load event doesn't seem possible either.

Or am I barking up the wrong tree?

+1  A: 

It isn't clear to me why you couldn't just solve this by explicitly calling a component's method from the form's Load event handler.

Making a component aware of the form on which it is dropped is possible. The designer can be coaxed to initialize a property of the component to the form instance. This is a technique used by ErrorProvider for example, it paints the error icons on the form. This could then be extended to let the component subscribe to the form's Load event. Here is an example:

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

namespace WindowsFormsApplication1 {
  public partial class Component1 : Component {
    public Component1() {
      InitializeComponent();
    }
    public Component1(IContainer container) {
      container.Add(this);
      InitializeComponent();
    }

    private ContainerControl mHost;
    public ContainerControl Host {
      get { return mHost; }
      set {
        if (mHost == null && value as Form != null && !DesignMode) {
          (value as Form).Load += Initialize;
        }
        mHost = value;
      }
    }

    public override ISite Site {
      set {
        base.Site = value;
        if (value != null) {
          // Assign Host at design time
          IDesignerHost service = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
          if (service != null) {
            IComponent rootComponent = service.RootComponent;
            this.Host = rootComponent as ContainerControl;
          }
        }
      }
    }
    private void Initialize(object sender, EventArgs e) {
      Console.WriteLine("initializing...");
    }
  }
}
Hans Passant
We already have a lot of forms, I was hoping to avoid going back and adding code to them all to fix this, but seems the most correct way to fix this is by doing so. I will look into the code you've posted.
Lasse V. Karlsen
The code you posted solved the problems. For existing forms, I have to go back and manually set the Host property, and with the code you posted, new forms will get this fixed automatically. Thanks!
Lasse V. Karlsen