views:

122

answers:

2

Hi there,

I want to implement a generic Observer Pattern for user controls. What is the best way to do this?

There are 3 usercontrols: A, B & C. Each of these usercontrols is a representation of a set of data. Each control has a select for display mode (basic or detailed). The site visitore gets to choose which mode. On changing the display mode on any one of the controls, the other controls should reflect that change.

The killer here is that the usercontrols can be addded dynamically to a page by the site visitor and as such the page may have any combination of controls including none of them. They may also feature on multiple aspx pages.

I was thinking the Observer Pattern is the best approach, is it? and if so are there any exmples on teh best way to achieve this?

Thanks, Richard

+1  A: 
Developer Art
The user experience is similar to a widget or gadget. Independent management by the user but with an option to update other widgets/gadgets to match this setting.
Richard Lennox
Then this book is for you. It's about a customizable widget-based user portal.
Developer Art
+1: Most creepy O'Reilly animal since the tarsier book.
Juliet
this provided me with enough information to complete my work. Thanks.
Richard Lennox
+1  A: 

I have dealt with multiple user controls which needed to respond to the same piece of user input.

I created a base page inherited from System.Web.UI.Page. I included the user input as a property here ( more on this later ).

I defined this interface

public interface IRespondToInput 
{
    int InputID 
    {
        get;
        set;
    }
}

Ok, it wasn't called that exactly, but each of the user controls that I wanted to see the change implemented. This interface consisted of a single property, which reflects the property in the base page.

public int InputID 
{
  get
  { 
    return _inputID 
  }
  set
  {
    _inputID = value;
    SetInputs(this, _inputID);
  }
}

In the setter of the base page method, I call a routine which recursively jumps through the control hierarchy, looking for anything implementing IRespondToInput, setting the property whenever a user control matching this interface was found. ( see code )

 protected void SetInputs( Control theControl, int theInputID )
    {
        if (theControl.Controls.Count > 0)
        {
            foreach (Control mySubControl in theControl.Controls)
            {
                if (mySubControl is UserControl || mySubControl is System.Web.UI.HtmlControls.HtmlForm)
                {
                    if (mySubControl is IRespondToInput)
                    {
                        ((IRespondToInput)mySubControl).InputID = theInputID;
                    }

                    SetInputs(mySubControl, theInputID);
                }
            }
        }
    }

This in turn, would trigger local binding events on the user control.

In truth, I could have called the property from the inherited page.

e.g. ( in user control code behind )

int mySetting = ((MyBasePage)Page).InputID;

I just wanted to drop compliant controls onto a compliant page and have them work. This approach may work for you.

Added for original poster

If you wish to avoid putting this logic in a derived base page, why not create a separate UserControl ( D - continuing your example ) which encapsulates your switching logic, but also finds all controls implementing the IRespondToInput interface?

In this UserControl, your setter would look like :-

public int InputID 
{
  get
  { 
    return _inputID 
  }
  set
  {
    _inputID = value;
    SetInputs(Page, _inputID);
  }
}

Incorporate this control as a sub-control of UserControls A, B and C.

This way, you don't have to make every page ADerivedPage - you can just put your UserControls onto the pages where you need them. And you'll be fine passing Page as a parameter, as it inherits from Control.

Paul Alan Taylor
I would prefer to avoid the page completely if at all possible.
Richard Lennox
Lemme know if the edit addresses your issue.
Paul Alan Taylor