Aug 10th 2008 09:06 am

Perils of Sys.UI.Component and Update Panels

When writing custom MS Ajax controls, deciding what framework class to inherit from on the client can be tricky. The MS Ajax documentation gives the following explanation of the Sys.UI.Component and it’s associated child classes here:

Client component object types Summary
Components
  • Derive from the Component base class.
  • Typically have no UI representation, such as a timer component that raises events at intervals but is not visible on the page.
  • Have no associated DOM elements.
  • Encapsulate client code that is intended to be reusable across applications.
Behaviors
  • Derive from the Behavior base class, which extends the Component base class.
  • Extend the behavior of DOM elements, such as a watermarking behavior that can be attached to an existing text box.
  • Can create UI elements, although they do not typically modify the basic behavior of the DOM element that they are associated with.
  • If assigned an ID, can be accessed directly from the DOM element through a custom attribute (expando).
  • Do not require an association with another client object, such as a class derived from the Control or Behavior classes.
  • Can reference either a control or a non-control HTML element in their element property.
Controls
  • Derive from the Control base class, which extends the Component base class.
  • Represent a DOM element as a client object, typically changing the original DOM element’s ordinary behavior to provide new functionality. For example, a menu control might read <li> items from a <ul> element as its source data, but not display a bulleted list.
  • Are accessed from the DOM element directly through the control expando.

If the difference between Behaviors and Controls isn’t clear to you, you’re not alone. In fact, depending on the version of microsoft documentation, or their horrific msdn documentation, these terms are used almost interchangeably. Generally, behavior, extender, control all refer to the same thing – some custom code written in javascript and instantiated via $create.

Following the documentation then, if an extender does not have a target control it should inherit from Sys.UI.Component.

Suppose we have a page that’s using update panels and depending on the user action an extender (inheriting from Sys.UI.Component) is written to the page.

When a postback occurs the extender will be rendered to the page again. Now there will be a new extender and an existing extender both with the same id. This will cause a javascript error that’s hard to track down, something like “Behavior with Id:? already exists”.

The original instance of the extender should have been disposed when the update panel framework reloaded the page. Since the extender didn’t have a target element (the core difference between Sys.UI.Component and Sys.UI.Behavior), the framework didn’t know to dispose the extender object when the update panel refreshed its content. 

To work around this, simply change the extender to inherit from Sys.UI.Behavior and giving it a target element. This will ensure that the object is disposed when the target element is disposed when either the update panel framework destroys the target element or the page is unloaded.

No Comments yet »

Trackback URI | Comments RSS

Leave a Reply

« Converting VB to C# while preserving project references and existing solutions | Binding MS Ajax Extenders to nested Controls »