我正在构建一个弹出菜单,客户希望它能够根据层次结构不断弹出。
例如,第一个窗格是选项列表。当它们悬停时,另一个窗格应在其旁边弹出下一级选项,依此类推,直到达到最后一级选项。
我可以处理所有的 javascript 和东西,但我想不出一种方法来不断地将转发器嵌入转发器中。我知道我可以通过将中继器放入另一个中继器来完成一次,但那时我将只有两层。
我需要能够为每一层选项持续嵌入中继器,或者使用不同的控件通过类似的技术来实现这一点。
任何帮助都很棒,谢谢!
您将无法在标记中构建它。您必须在代码中动态添加控件,方法是为每个级别构建中继器并将其添加到前一个中继器的模板中。它需要对每个选择的选项进行完整的回发,因为嵌套的中继器可能具有不同的深度,具体取决于选择的选项。
不过,使用 AJAX 和 javascript 在所有客户端执行此操作可能会更好。选择选项时,请从Ajax请求中触发,以查看该选项是否具有子选项。如果是(返回它们),则使用 javascript 动态构建新的选项控件并将其添加到页面中。选择不同的选项时,您将从包含先前所选选项子选项中的DOM中删除元素。
如果您可以以MenuItem
对象列表的形式获取菜单,每个对象都有一个(有时是空的)子项目列表(我的意思是List<MenuItem>
这里......我们将使用这个集合作为数据源一个子中继器,所以它需要实现IEnumerable<T>
) 作为一个属性MenuItem.SubItems
,你可能会使用一个UserControl
循环出一个菜单级别的 a ,并在下一个菜单级别调用它自己。
在UserControl
你会有这样的事情:
<li><a href='<%= this.MenuItem.Url %>'><%= this.MenuItem.LinkText %></a></li>
<asp:Repeater ID="UCRepeater" runat="server">
<HeaderTemplate>
<ul>
<ItemTemplate>
<menu:MenuItem ID="MenuItemUC" runat="server" />
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
UserControl
中的是ItemTemplate
相同的,因此对于每个项目模板,将呈现相同的内容。
下面是这个用户控件的代码,这就是神奇的地方:
public partial class MenuItemUserControl : UserControl
{
// A property we'll use as the data source
public MenuItem MenuItem { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
// If the current menu item has sub items, we bind the repeater to them
// And by the way, there is no use doing this on every postback. First
// page load is good enough...
if(!Page.IsPostBack) {
{
if(MenuItem.SubItems.Count > 0)
{
UCRepeater.DataSource = MenuItem.SubItems;
UCRepeater.DataBind();
}
}
}
protected void UCRepeater_OnItemDataBound(object sender,
RepeaterDataBoundEventArgs e)
{
// Every time an Item is bound to the repeater, we take the current
// item which will be contained in e.DataItem, and set it as the
// MenuItem on the UserControl
// We only want to do this for the <ItemTemplate> and
// <AlternatingItemTemplate>
if(e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
var uc = (MenuItemUserControl)e.Item.FindControl("MenuItemUC");
if(uc != null)
{
// This is the magic. Abrakadabra!
uc.MenuItem = (MenuItem)e.DataItem;
}
}
}
}
所以为了让它工作,唯一缺少的是一个很好的方法,可以将数据作为MenuItem
s 的分层列表取出。我将把这个留给您的数据访问层(使用 LINQ to SQL 或实体框架会很便宜...;))
免责声明:此代码按原样提供,我是在脑海中写下的。我没有测试过它,但我认为它会起作用——如果它不起作用,它至少可以让你知道如何解决这个问题。如果您有问题,请在评论中发布它们,我会尽力提供帮助 - 但这里没有成功的承诺。只是愿意帮忙!=)