views:

1230

answers:

5

The scenario: 2 user controls (foo.ascx and fum.ascx)

foo has a method that would really like to access a property from fum. They live on the same page, but I can't find a very simple way to accomplish this sort of communication.

Any ideas?

A: 

Add an event to the UserControl that is hooked up to the form.

Craig
+3  A: 
  • Add an event OnMyPropertyValueChanged in fum.ascx.
  • Add the corresponding EventHandler to foo.ascx which stores the property value in a private variable.
  • Attach the event handler of foo.ascx to the event of fum.ascx on Page_Load.
  • Raise the event on fum.ascx Page_Load and whenever needed
  • Let the method of foo.ascx use its own variable
Panos
who does the attaching? the Page? that creates a dependency of the page knowing about the two controls relationship - increasing coupling and dependency.
Samuel Kim
Samuel, note that the page is the ONE and ONLY thing that knows the control relationship. The two controls do NOT know that are related.
Panos
A: 

The simplest solution is for fum to store a value in HttpContext.Current.Items[], where foo can read it later.

A more robust option is to give foo a property that the the page can populate with a reference to fum.

An event is more work, but is architecturally nicer.

stevemegson
+1  A: 

There are a few ways to handle this, but optimally you want a solution that is as decoupled as possible.

The most decoupled method would be a recursive findControl method that walks the control object model until it finds the control you want and returns a reference.

private Control findControl(Control root, string id) 
{ 
    if (root.ID == id)
    { 
        return root; 
    } 

    foreach (Control c in root.Controls) 
    { 
        Control t = findControl(c, id); 
        if (t != null) 
        { 
            return t; 
        } 
    } 

    return null; 
}

Here is another approach that is kinda neat, though I don't know if I'd use it.(Somewhat pseudocode):

public FunkyUserControl : UserControl
{
    private List<UserControl> subscribedControls;

    public List<UserControl> Subscribers
    {
        get { return subscribedControls;}
    }

    public void SubscribeTo(UserControl control)
    {
        subscribedControls.Add(control);
    }
}

Inherit your two usercontrols from FunkyUserControl and then in your main page class you can do:

webControl1.SubscribeTo(webControl2);
webControl2.SubscribeTo(webControl1);

Now each control can introspect its subscribers collection to find the other control.

FlySwat
Jonathan, the findControl() approach works only if the target control is a parent of the source control. Usually this is not the case... Moreover, if you want to find a control by id, you can use Page.FindControl(id), which search the full tree.
Panos
Eh your right, I posted the wrong findControl. I should have posted my recursive one that walks the entire tree.If I recall right, Page.FindControl only goes one level deep.
FlySwat
There fixed... Page.FindControl won't search deeper than one naming container btw.
FlySwat
With FindControl() be aware that there could be multiple controls with same ids inside a tree of controls (any repeater type control being prime example).
Samuel Kim
You're right about the naming containers, although in this case the naming container is the page. Concerning decoupling, what is your suggestion for passing to foo control the id of fum control in order to use the findControl()?
Panos
you are making assumptions about where the user control is - it could be inside a panel (naming container) or even inside another user control.
Samuel Kim
A: 

You can reference the other user control by using FindControl on Foo's Parent. This is the simplest and you don't need to program anything on each main (parent) form.

'From within foo...call this code
Dim objParent As Object
Dim lngPropID As Long

objParent = Me.Parent.FindControl("fum")
lngPropID= objParent.PropID 'public property PropID on fum