views:

4411

answers:

4

I am writing a Composite control, which contains a listview to display a table of items. Normally when using a ListView in Asp.NET I would define the templates in the code-forward.

<asp:ListView runat="server" ID="ArticleList">
    <LayoutTemplate>
        <div class="ContentContainer">
            <div runat="server" id="itemPlaceholder" />
        </div>
    </LayoutTemplate>
    <ItemTemplate>
        <div>
            <div><%# Eval("Content") %></div>
        </div>
    </ItemTemplate>
    </asp:ListView>

I assume it's something like:

ListView view = new ListView();
view.LayoutTemplate = .....
view.ItemTemplate = .....

// when do I call these?
view.DataSource = myDataSource;
view.DataBind();

Update: I created 2 templates by implementing the ITemplate interface:

private class LayoutTemplate : ITemplate
{
    public void InstantiateIn(Control container)
    {
        var outer = new HtmlGenericControl("div");
        var inner = new HtmlGenericControl("div") { ID = "itemPlaceholder" };
        table.Rows.Add(row);

        container.Controls.Add(table);
    }
}

private class ItemTemplate : ITemplate
{
    public void InstantiateIn(Control container)
    {
        var inner = new HtmlGenericControl("div");

        container.Controls.Add(inner);
    }
}

and I can add them using:

dataList.LayoutTemplate = new LayoutTemplate();
dataList.ItemTemplate = new ItemTemplate();

But then I get stuck, since container.DataItem is null.

+2  A: 

Could this link be of some help? Using Templated Controls Programmatically

Generating the Templates at Design-Time (in order to persist them in the aspx file) is a little bit trickier, but the DataBinding will work automatically.

Pau
Looks like it might.
pb
A: 

Setup a class like:

public delegate void InstantiateTemplateDelegate(Control container);

public class GenericTemplateImplementation : ITemplate
{
 private InstantiateTemplateDelegate instantiateTemplate;

 public void InstantiateIn(Control container)
 {
  this.instantiateTemplate(container);
 }

 public GenericTemplateImplementation(InstantiateTemplateDelegate instantiateTemplate)
 {
  this.instantiateTemplate = instantiateTemplate;
 }
}

And then do the following:

 view.LayoutTemplate = new GenericTemplateImplementation(p =>
                {
                    p.Controls.Add(new Label { Text = "Foo" });
                });
sontek
+4  A: 

The trick is to subscribe to the databinding event of the itemplaceholder in the ItemTemplate.

The complete solution:

public class FibonacciControl : CompositeControl
{
    public FibonacciControl()
    {
        // ....
    }

    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        ListView view = new ListView();

        view.LayoutTemplate = new LayoutTemplate();
        view.ItemTemplate = new ItemTemplate();

        view.DataSource = FibonacciSequence();
        view.DataBind();

        this.Controls.Add(view);
    }

    private IEnumerable<int> FibonacciSequence()
    {

        int i1 = 0;
        int i2 = 1;

        for (int i = 0; i < Iterations; i++)
        {
            yield return i1 + i2;
            int temp = i1 + i2;
            i1 = i2;
            i2 = temp;
        }
        yield break;
    }

    public int Iterations { get; set; }

    private class LayoutTemplate : ITemplate
    {

        public void InstantiateIn(Control container)
        {
            var ol = new HtmlGenericControl("ol");
            var li = new HtmlGenericControl("li") { ID = "itemPlaceholder" };
            ol.Controls.Add(li);

            container.Controls.Add(ol);
        }
    }

    private class ItemTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            var li = new HtmlGenericControl("li");

            li.DataBinding += DataBinding;
            container.Controls.Add(li);
        }

        public void DataBinding(object sender, EventArgs e)
        {
            var container = (HtmlGenericControl)sender;
            var dataItem = ((ListViewDataItem)container.NamingContainer).DataItem;

            container.Controls.Add( new Literal(){Text = dataItem.ToString() });
        }
    }
}
pb
A: 

Building on Sonteks example here is an example that creates a template that contains elements that are then bound using databinding.

public partial class View : PortalModuleBase
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    #region MasterListView_ItemDataBound
    public void MasterListView_ItemDataBound(object sender, ListViewItemEventArgs e)
    {
        ListViewItem objListViewItem = (ListViewItem)e.Item;
        ListViewDataItem objListViewDataItem = objListViewItem as ListViewDataItem;

        if (objListViewDataItem != null)
        {
            Tab objTab = (Tab)objListViewDataItem.DataItem;
            IEnumerable<Tab> Tabs = CustomData(objTab.TabID);

            Label TabIDLabel = (Label)objListViewItem.FindControl("TabIDLabel");
            Label TabNameLabel = (Label)objListViewItem.FindControl("TabNameLabel");

            TabIDLabel.Text = objTab.TabID.ToString();
            TabNameLabel.Text = objTab.TabName;

            AddListView(objTab.TabName, objListViewItem, Tabs);
        }
    }
    #endregion

    #region CustomData
    static IEnumerable<Tab> CustomData(int? ParentID)
    {
        TabAdminDataContext objTabAdminDataContext = new TabAdminDataContext();

        var myCustomData = from Tabs in objTabAdminDataContext.Tabs
                           where Tabs.ParentId == ParentID
                           select Tabs;

        return myCustomData.AsEnumerable();
    }
    #endregion

    #region AddListView
    private void AddListView(string CurrentTabName, Control container, IEnumerable<Tab> ChildTabs)
    {
        // The Tab has Children so add a ListView
        if (ChildTabs.Count() > 0)
        {
            ListView ChildListView = new ListView();
            ChildListView.ID = "ChildListView";
            ChildListView.ItemCommand += ListView_ItemCommand;
            ChildListView.EnableViewState = true;
            ChildListView.LayoutTemplate = new MyLayoutTemplate();
            ChildListView.ItemTemplate = new MyItemTemplate();
            ChildListView.DataSource = ChildTabs;
            ChildListView.DataBind();

            // Put the ListView in a Panel
            var oTR = new HtmlGenericControl("tr") { ID = "ChildListViewTR" };
            var oTD = new HtmlGenericControl("td") { ID = "ChildListViewTD" };

            Panel objPanel = new Panel();
            objPanel.ID = "ListViewPanel";
            objPanel.ToolTip = CurrentTabName;
            objPanel.Controls.Add(ChildListView);

            oTD.Controls.Add(objPanel);
            oTR.Controls.Add(oTD);
            container.Controls.Add(oTR);
        }
    }
    #endregion

    #region ListView_ItemCommand
    protected void ListView_ItemCommand(object sender, ListViewCommandEventArgs e)
    {
        LinkButton objButton = (LinkButton)sender;
        Label1.Text = objButton.Text;
        MasterListView.DataBind();
    }
    #endregion

    #region MyLayoutTemplate
    public class MyLayoutTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            var oTR = new HtmlGenericControl("tr") { ID = "itemPlaceholder" };
            container.Controls.Add(oTR);
        }
    }
    #endregion

    #region ItemTemplate
    public class MyItemTemplate : ITemplate
    {
        public void InstantiateIn(Control container)
        {
            var oTR = new HtmlGenericControl("tr");

            var oTD1 = new HtmlGenericControl("td");
            LinkButton TabIDLinkButton = new LinkButton();
            TabIDLinkButton.ID = "TabIDLinkButton";
            oTD1.Controls.Add(TabIDLinkButton);
            oTR.Controls.Add(oTD1);

            var oTD2 = new HtmlGenericControl("td");
            Label TabNameLabel = new Label();
            TabNameLabel.ID = "TabNameLabel";
            oTD2.Controls.Add(TabNameLabel);
            oTR.Controls.Add(oTD2);

            oTR.DataBinding += DataBinding;
            container.Controls.Add(oTR);
        }

        public void DataBinding(object sender, EventArgs e)
        {
            var container = (HtmlGenericControl)sender;
            var dataItem = ((ListViewDataItem)container.NamingContainer).DataItem;
            Tab objTab = (Tab)dataItem;

            LinkButton TabIDLinkButton = (LinkButton)container.FindControl("TabIDLinkButton");
            Label TabNameLabel = (Label)container.FindControl("TabNameLabel");

            TabIDLinkButton.Text = "+" + objTab.TabID.ToString();
            TabNameLabel.Text = objTab.TabName;

            IEnumerable<Tab> ChildTabs = View.CustomData(objTab.TabID);

            View objView = new View();
            objView.AddListView(objTab.TabName, container, ChildTabs);
        }

    }
    #endregion

}
Michael Washington