DataBinding to a subcontrol...

Discussion in 'ASP .Net Building Controls' started by Fred Hirschfeld, Sep 18, 2004.

  1. I am creating a new web control that will be a DropDownList that gets its
    values dynamically from a Web Service based on user selections on the form
    (client side). I have created the control and it has a collection of classes
    that reference other webcontrols on the page. These referenced control are
    the ones that drive the variable values passed as parameters to the web
    service.

    So for example I have DropDown1 control on the page that is a standard
    DropDownList that is populated on the server using DataBind(). I have my new
    control on the page and through the designer add the reference to DropDown1
    to the property collection on DropDown2 (the new control that uses
    services).

    At design-time (initially) this all appears to be working but when I execute
    the page, I get an error that the reference is NULL. I debug and see that
    the objects are all created but the reference is not there in my custom
    control. I have followed some descriptions I found that indicate the only
    way to do this is to follow the DataBinding method use by DataSource (and
    why my collection takes a Control derived class instead of a regular class).
    Also, if I try to redesign the page, the bound control no longer has the
    data binding.

    I have tested the technique (and code I have) on a property on the base
    control (rather than a collection) and it does maintain the designable
    aspect and the code binds properly.

    public class DropDownServicedList : WebControl {
    ...

    private CustomCollection m_BoundParameters = new CustomCollection();

    [
    PersistenceMode(PersistenceMode.InnerProperty),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
    NotifyParentProperty(true)
    ]
    public CustomCollection BoundParameters {
    get { return m_BoundParameters; }
    }

    ...
    }

    public class CustomCollection : CollectionBase {
    ... standard implementation ...
    }

    // Derived from control for databinding...
    [Designer("SierraSystems.Web.Controls.Design.BoundParameterControlDesigner,
    SierraSystems.Web")]
    public class BoundParameterControl : Control
    {
    private string m_ParameterName = string.Empty;
    private WebControl m_BoundControl = null;

    [NotifyParentProperty(true)]
    public string ParameterName
    {
    get { return m_ParameterName; }
    set { m_ParameterName = value; }
    }

    [
    Browsable(true),
    Bindable(true),
    PersistenceMode(PersistenceMode.InnerProperty),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
    NotifyParentProperty(true)
    ]
    public WebControl BoundControl
    {
    get { return m_BoundControl; }
    set { m_BoundControl = value; }
    }

    [
    Browsable(false),
    Bindable(false),
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
    ]
    public string BoundControlID
    {
    get
    {
    if (m_BoundControl != null)
    return m_BoundControl.ClientID;

    return string.Empty;
    }
    }

    public BoundParameterControl()
    {
    }

    public string GetControlValueJavascript()
    {
    return string.Format("{0}.options[{0}.selectedIndex].value",
    m_ParameterName);
    }
    }

    public class BoundParameterControlDesigner : ControlDesigner
    {
    public string BoundControl
    {
    get
    {
    DataBinding binding = DataBindings["BoundControl"];

    if (binding != null)
    {
    return binding.Expression;
    }

    return string.Empty;
    }
    set
    {
    if ((value == null) || (value.Length == 0))
    {
    DataBindings.Remove("BoundControl");
    }
    else
    {
    DataBinding binding = DataBindings["BoundControl"];

    if (binding == null)
    {
    binding = new DataBinding("BoundControl", typeof(WebControl), value);
    }
    else
    {
    binding.Expression = value;
    }
    DataBindings.Add(binding);
    }

    OnBindingsCollectionChanged("BoundControl");

    IContainer container = (IContainer)this.GetService(typeof(IContainer));
    ((BoundParameterControl)this.Component).BoundControl =
    container.Components[value] as WebControl;
    }
    }

    protected override void PreFilterProperties(IDictionary properties)
    {
    base.PreFilterProperties(properties);

    PropertyDescriptor prop = (PropertyDescriptor)properties["BoundControl"];

    System.ComponentModel.AttributeCollection runtimeAttributes =
    prop.Attributes;
    Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];

    runtimeAttributes.CopyTo(attrs, 0);
    attrs[runtimeAttributes.Count] = new
    TypeConverterAttribute(typeof(BoundParameterControlTypeConverter));
    prop = TypeDescriptor.CreateProperty(this.GetType(), "BoundControl",
    typeof(string), attrs);
    properties["BoundControl"] = prop;
    }
    }



    public override StandardValuesCollection
    GetStandardValues(ITypeDescriptorContext context)
    {
    object[] components = null;

    if (context != null)
    {
    ArrayList list = new ArrayList();
    list.Add(null);

    IContainer cont = context.Container;
    if (cont != null)
    {
    ComponentCollection objs = cont.Components;
    foreach(IComponent obj in objs)
    {
    if (obj is DropDownList || obj is DropDownServicedList)
    {
    list.Add(obj.Site.Name);
    }
    }
    }

    components = list.ToArray();
    }

    return new StandardValuesCollection(components);
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext
    context)
    {
    return true;
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext
    context)
    {
    return true;
    }
    }


    Any ideas? I can add mode code here if it will help but there is a lot of it
    and so I don't want to add it to this initial post. Below is the snippet of
    HTML that is produced...



    <sierra:dropdownservicedlist id="ddlActivities" runat="server"
    UseSelectItem="True" ValueMember="@ActivityId"
    ServiceURL="~/Services/DataLists.asmx/GetActivitiesByGroup"
    SelectItemText="-- Select an Activity --">
    <ParameterControls>
    <sierra:BoundParameterControl ID="boundParameterControl1"
    ParameterName="test" BoundControl='<%# ddlGroup %>'>
    </sierra:BoundParameterControl>
    </ParameterControls>
    </sierra:dropdownservicedlist>

    <!---------------------- Custom
    DropDownList ----------------------------------->
    Fred Hirschfeld, Sep 18, 2004
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bonj
    Replies:
    1
    Views:
    2,055
    John M Deal
    Nov 13, 2004
  2. Ben Dewey
    Replies:
    3
    Views:
    4,838
    Ben Dewey
    Nov 1, 2005
  3. James Geurts

    Getting a subcontrol to work in a repeater

    James Geurts, Feb 17, 2004, in forum: ASP .Net Building Controls
    Replies:
    3
    Views:
    109
    Jeffrey Tan[MSFT]
    Feb 18, 2004
  4. Bonj

    setting focus to datagrid subcontrol

    Bonj, Nov 13, 2004, in forum: ASP .Net Datagrid Control
    Replies:
    1
    Views:
    104
    Michelle Hlaing
    Nov 17, 2004
  5. Mark Friedman
    Replies:
    0
    Views:
    137
    Mark Friedman
    Jul 9, 2003
Loading...

Share This Page