Search code examples
asp.netdata-bindingcustom-controlsdataitem

Databinding on Custom Control with ITemplate


this is a sample code of my custom server control :

[Designer(typeof(ContainerControlDesigner))]
[ToolboxData("<{0}:BlocArrondi runat=server><ContenuPrincipal></ContenuPrincipal></{0}:BlocArrondi>")]
public class BlocArrondi : WebControl
{
    private ITemplate _ContenuPrincipal;
    protected Panel _PanelContenuPrincipal = new Panel();

    public BlocArrondi()
    : base(HtmlTextWriterTag.Div)
    {

    }

    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateInstance(TemplateInstance.Single)]
    public ITemplate ContenuPrincipal
    {
            get { return _ContenuPrincipal; }
            set { _ContenuPrincipal = value; }
    }

    protected override void OnInit(EventArgs e)
    {
            base.OnInit(e);
            _PanelContenuPrincipal.ID = "PanelPrincipal";
            this.Controls.Add(_PanelContenuPrincipal);

            if (_ContenuPrincipal != null)
                    _ContenuPrincipal.InstantiateIn(_PanelContenuPrincipal);
    }
}

and here the implementation :

<controls:BlocArrondi runat="server">
    <ContenuPrincipal>
        <asp:Label id="LabelInfo" runat="server" />
    </ContenuPrincipal>
</controls:BlocArrondi>

My label LabelInfo is accessible on the code behind, great !

But if i use my custom control in a Repeater or a ListView, i can't use the Container.DataItem property inside the ContenuPrincipal Template :

<asp:Repeater id="RepeaterInfos" runat="server">
    <ItemTemplate>
        <controls:BlocArrondi runat="server">
            <ContenuPrincipal>
                <asp:Label runat="server" Text="<%# (Container.DataItem as MsgInfo).DisplayMessage() " />
            </ContenuPrincipal>
        </controls:BlocArrondi>
    </ItemTemplate>
</asp:Repeater>

The error message :

'System.Web.UI.Control' does not contain a definition for 'DataItem' and no extension method 'DataItem' accepting a first argument of type 'System.Web.UI.Control' could be found (are you missing a using directive or an assembly reference?)

How can i use the Container.DataItem property inside the ContenuPrincipal Template of my control ?


Solution

  • I Solved my problem with a custom TemplateContainer inherit from IDataItemContainer :

        public class BlocArrondiContainer : Panel, IDataItemContainer
    

    Change :

        protected Panel _PanelContenuPrincipal = new Panel();
    
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateInstance(TemplateInstance.Single)]
        public ITemplate ContenuPrincipal
        {
            get { return _ContenuPrincipal; }
            set { _ContenuPrincipal = value; }
        }
    

    By :

        protected BlocArrondiContainer _PanelContenuPrincipal = new BlocArrondiContainer ();
    
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateInstance(TemplateInstance.Single)]
        [TemplateContainer(typeof(BlocArrondiContainer))]
        public ITemplate ContenuPrincipal
        {
            get { return _ContenuPrincipal; }
            set { _ContenuPrincipal = value; }
        }
    

    Overrinding the OnDataBinding method on the BlocArrondi class :

        protected override void OnDataBinding(System.EventArgs e)
        {
            if (NamingContainer is IDataItemContainer)
                _PanelContenuPrincipal.DataItem = (NamingContainer as IDataItemContainer).DataItem;
    
            base.OnDataBinding(e);
        }