ASP Repeater控件多模板使用方法

5

如何使用具有多个模板的重复器控件,其中所选择的模板基于项目的类型?

目前我拥有以下内容:

我的重复器类:

[ToolboxData("<{0}:LifestreamRepeater runat=server>")]
public class LifestreamRepeater : Repeater
{

    [PersistenceMode(PersistenceMode.InnerProperty)]
    public ITemplate TwitterTemplate {get; set;}


    protected override void OnDataBinding(EventArgs e)
    {
        //base.OnDataBinding(e);
        foreach (var item in (IEnumerable<LifestreamItem>)this.DataSource)
        {
            if (item is LifestreamTwitterItem)
            {
                LifestreamRepeaterItem ri = new LifestreamRepeaterItem(item);
                TwitterTemplate.InstantiateIn(item);
            }
            else
            {
                ItemTemplate.InstantiateIn(item);
            }
        }

    }
}

同时还有前端技术:

        <lfs:LifestreamRepeater runat="server" ID="repeater1">
            <TwitterTemplate>
                <div class="Lifestream Twitter Item">
                    <h4> <%# DataBinder.Eval(Container.DataItem, "Title")%> </h4>
                    <p>  <%# DataBinder.Eval(Container.DataItem, "Body")%> </p>
                </div>
            </TwitterTemplate>
            <ItemTemplate>
                <div class="Lifestream Item">
                    <h2> <%# DataBinder.Eval(Container.DataItem, "Title")%> </h2>
                    <p>  <%# DataBinder.Eval(Container.DataItem, "Body")%> </p>
                </div>
            </ItemTemplate>
        </lfs:LifestreamRepeater>

然后我将重复控件绑定到LifestreamItem的IEnumerable,它是多种不同社交网络帖子类型的基类,因此可能存在TwitterLifestreamItem和VimeoLifestreamItem,我希望重复控件根据数据项选择不同的模板,并具有不同的可能值。


类似问题:https://dev59.com/PW035IYBdhLWcg3wPdkS - Alex
这是一个有用的链接,显示了所有必需的模板属性(否则不会工作所有功能,例如Container.ItemIndex):https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.repeater.itemtemplate?view=netframework-4.8 - Alex
2个回答

2

看起来解决方案是像这样重写DataBind方法:

    public override void DataBind()
    {
        foreach (var item in (IEnumerable<LifestreamItem>)this.DataSource)
        {
            if (item is LifestreamTwitterItem)
            {
                TwitterTemplate.InstantiateIn(item); // instantiate inside the item which is also a control.
            }
            else
            {
                ItemTemplate.InstantiateIn(item);
            }
            item.DataBind(); // bind the item
            Controls.Add(item); // add the item to the repeater
        }
    }

1

我不认为ASP.NET内置了允许此操作的内容,但你可以这样做:

<asp:Repeater ID="myRepeater" runat="server" OnItemDataBound="myRepeater_ItemDataBound">
    <ItemTemplate>
        <asp:PlaceHolder ID="twitterTemplate" Visible="false" runat="server">
             <asp:Literal ID="fooTwitterControl" runat="server" />
        </asp:PlaceHolder>

        <asp:PlaceHolder ID="itemTemplate" Visible="false" runat="server">
             <asp:Literal ID="fooItemControl" runat="server" />
        </asp:PlaceHolder>
    </ItemTemplate>
</asp:Repeater>

并且是 ItemDataBound 事件:

protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (ListItemType.Item == e.Item.ItemType || ListItemType.AlternatingItem == e.Item.ItemType)
    {
        PlaceHolder twitterTemplate = (PlaceHolder)e.Item.FindControl("twitterTemplate");
        PlaceHolder itemTemplate = (PlaceHolder)e.Item.FindControl("itemTemplate");

        var item = (LifestreamItem)e.Item.DataItem;
        if (item is LifestreamTwitterItem)
        {
            twitterTemplate.Visible = true;

            Literal fooTwitterControl = (Literal)e.Item.FindControl("fooTwitterControl");
            // Load all twitter related controls + populate
        }
        else
        {
            itemTemplate.Visible = true;
            Literal fooItemControl = (Literal)e.Item.FindControl("fooItemControl");
            // Load all non-twitter controls + populate
        }
    }
}

基本上,ItemTemplates 变成占位符,并根据您正在迭代的类型启用/禁用。

虽然那样做可以行得通,但我真正想要的是设计师能够轻松直接使用的东西。我能制作一个自定义控件来实现这个吗? - Calin Leafshade
@Steve 是的,创建一个自定义控件相对来说比较容易。只需要从“repeater”类继承即可。 - DGibbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接