3
votes

Currently I have a C# program with a windows form and then a user control template put onto the form. The user control template is really just used as a placeholder. I have a series of other controls which inherit from this user control template.

Each of those controls have navigation buttons like 'Continue' and 'Back' on them and each control knows which control needs to be loaded next. However what I need to figure out is an easier way to have variables that are global to these controls.

The only workaround I have is that I pass the form to each control when they are loaded and use variables inside of the form to read and write to. What would be the proper way to have each of these user control screens be built off of a base control which contained objects all of the controls could get to?

Sorry for the rambling nature of the post but I've been thinking about this problem all morning.

Here is some of the code:

Most of what I have written was based on hiding and showing the user controls so that content in the controls wouldn't be lost during navigation. I won't be needing to do that as eventually it will be loading the fields of data from a database.

Code for initially loading control from form click:

        conTemplate1.Controls.Clear();
        conInbound Inbound = new conInbound(this);
        Inbound.Dock = DockStyle.Fill;
        Inbound.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
        conTemplate1.Controls.Add(Inbound);

Code for Continue button inside of one of the controls:

    if ((Parent.Controls.Count - 1) <= Parent.Controls.IndexOf(this))
        {
            UserControl nextControl = new conPartialClear();
            nextControl.Dock = DockStyle.Fill;
            Parent.Controls.Add(nextControl);
            this.Hide();
            Parent.Controls[Parent.Controls.IndexOf(this) + 1].Show();
        }
        else
        {
            this.Hide();
            Parent.Controls[Parent.Controls.IndexOf(this) + 1].Show();
        }
2

2 Answers

2
votes

The best-practice for communicating from a control to a parent is to use events, and for communicating from a parent to a control is to call methods.

However, if you don't want to or can't follow this practice, here's what I would recommend.

Each UserControl has a ParentForm property that returns the Form that contains the control. If you know that the UserControl will always be attached to MyParentForm, you just cast the ParentForm and then you can access all public controls, methods, etc.

Here's what I mean:

public class conTemplate
{
    public MyParentForm MyParentForm
    {
        get
        {
            return (MyParentForm)this.ParentForm;
        }
    }
}

This way, you can easily access any public members of MyParentForm. Your conInbound class could have code such as this.MyParentForm.GlobalSettings.etc..., and could even have access to any public controls.

0
votes

I'm not totally sure I understand your problem. It sounds like you want the user control to "do something" with it's parent form. If that's the case, you may want to consider adding events to the UC and then handle them on the form itself.

Basically, for your UC's "continue", you'll have an event that's fired when it's pressed. You'll want to handle that in your form. I'm not real sure about the syntax from memory, or I'd work something out for you code-wise. But I think that's the route you'll want to take. Think of your UC like any other windows form control. If you add a button to your form, you assign it it's event method. Do the same with the UC.

I found this and thought it may be helpful. Scroll down to where it talks about UC's and events. http://www.akadia.com/services/dotnet_user_controls.html

Hope this helps.

EDIT after new info from OP.

You could declare a global variable inside the UC of type yourForm and then set that variable to the ParentForm at run-time, if I'm understanding you correctly.

So, inside your UC Class, you could do:

private parentFormInstance;

then inside the constructor of the UC, you could set it as such:

parentFormInstance = this.ParentForm; (or whatever the property name is).

This allows you at design-time to use:

parentFormInstance.DoSomething();

without the compiler yelling at you.

Just basic advice, but if you can go back and make it easier on yourself, even if it takes some additional time re-working things, it'd be worth it. It may save you time in the long run.