是否可以在asp:ListView中定义两个项目模板?

时间:2012-07-15 14:46:04

标签: c# asp.net .net

是否可以在listview中执行以下操作?如果不。请纠正我。

    <asp:ListView runat="server" ID="lsit">
    <LayoutTemplate>
        <div id="banner">
            <div id="paginate-slider2" class="banner_nav">
                <asp:PlaceHolder runat="server" ID="itemPlaceHolder1" />
            </div>
            <div id="slider2">
                <asp:PlaceHolder runat="server" ID="itemPlaceHolder2" />
            </div>
            <script src="/scripts/banner.js" type="text/javascript"></script>
        </div>
        <div class="clear"></div>
    </LayoutTemplate>
    <ItemTemplate>
        <a href="#" class="toc">
            <img src="./images/gallery/thumbnails/thumb1.gif" alt="" />
        </a> 
    </ItemTemplate>
    <ItemTemplate>
        <div class="contentdiv banner_sec">
            <div class="con_img">
                <img src="./images/gallery/images/img1.gif" alt="" />
            </div>
            <div class="con_desc">
                <h3>Featured</h3>
                <h5>Lorem ipsum dolor sit amet</h5>
                <p>
                    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed elit.
                </p>
                <br />
                <a href="./detail.html" class="buttontwo"><span>Read More</span></a>
            </div>
        </div>
    </ItemTemplate>
</asp:ListView>

更新: 我想输出这样的东西;

<!-- Home Banner Section -->
<div id="banner">
    <div id="paginate-slider2" class="banner_nav">
        <!-- this should be repeated for each item -->

        <a href="#" class="toc">
            <img src="./images/gallery/thumbnails/thumb1.gif" alt="" />
        </a> 
    </div>
    <div id="slider2">
        <!-- this should be repeated for each item -->
        <div class="contentdiv banner_sec">
            <div class="con_img">
                <img src="./images/gallery/images/img1.gif" alt="" />
            </div>
            <div class="con_desc">
                <h3>Featured</h3>
                <h5>Lorem ipsum dolor sit amet</h5>
                <p>
                    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed elit. Nulla sem risus, vestibulum in, volutpat eget, dapibus ac, lectus. Curabitur dolor sapien, hendrerit non, suscipit bibendum, auctor ac, arcu. Vestibulum dapibus. Sed pede lacus, pretium in, condimentum sit amet, mollis dapibus, magna. Ut bibendum dolor nec augue. Ut tempus luctus metus. Sed a velit. Pellentesque at libero elementum ante condimentum sollicitudin. Pellentesque lorem ipsum, semper quis, interdum et, sollicitudin eu, purus. Vivamus fringilla ipsum vel orci.
                </p>
                <br />
                <a href="./detail.html" class="buttontwo"><span>Read More</span></a>
            </div>
        </div>
    </div>
    <script src="/scripts/banner.js" type="text/javascript"></script>
</div>
<div class="clear"></div>

1 个答案:

答案 0 :(得分:4)

  

是否可以在asp:ListView中定义两个项目模板?

是的,这是可能的。 Read this post(当我正确格式化代码时,我会在此处发布代码,因此不会丢失。)

现金:

Dino Esposito是IDesign架构师,也是Programming ASP.NET 3.5 Core Reference的作者。 Dino总部位于意大利,经常在全球的行业活动中发表演讲。您可以通过cutting@microsoft.com与他联系,或者通过weblogs.asp.net/despos加入他的博客。

多个项目模板

ListView控件通过循环数据源并应用以下算法来生成其标记。首先,它检查是否需要项目分隔符。如果是,则实例化模板并创建数据项对象。数据项对象是项模板的容器,并携带有关视图中项的索引和绑定数据源的信息。实例化项目模板时,将触发ItemCreated事件。下一步是数据绑定。完成此操作后,将触发ItemDataBound事件。

正如您所看到的,没有可以处理的公共事件允许以编程方式更改每个项目的模板。您可以在Init或Load页面事件中更改模板,但这将适用于所有绑定项目。如果您处理ItemCreated并在其中设置ItemTemplate属性,则更改将影响下一个项目,但不会影响当前正在处理的项目。您需要一个ItemCreating事件,但ListView控件不会触发此类事件。然后,解决方案是创建自己的ListView控件,如图6所示。

图6解雇ItemCreating事件

namespace Samples.Controls
{
  public class ListViewItemCreatingEventArgs : EventArgs
  {
    private int _dataItemIndex;
    private int _displayIndex;

    public ListViewItemCreatingEventArgs(int dataItemIndex,
                                         int displayIndex) {
      _dataItemIndex = dataItemIndex;
      _displayIndex = displayIndex;
    }

    public int DisplayIndex {
      get { return _displayIndex; }
      set { _displayIndex = value; }
    }

    public int DataItemIndex {
      get { return _dataItemIndex; }
      set { _dataItemIndex = value; }
    }
  }

  public class ListView : System.Web.UI.WebControls.ListView
  {
    public event EventHandler<ListViewItemCreatingEventArgs>
                                               ItemCreating;

    protected override ListViewDataItem CreateDataItem(int
                           dataItemIndex, int displayIndex) {
      // Fire a NEW event: ItemCreating
      if (ItemCreating != null)
        ItemCreating(this, new ListViewItemCreatingEventArgs
                             (dataItemIndex, displayIndex));

      // Call the base method
      return base.CreateDataItem(_dataItemIndex, displayIndex);
    }
  }
}

通过重写CreateDataItem方法,您可以在实例化项目模板之前运行代码。 CreateDataItem方法在ListView类中声明为protected和virtual。如图6所示,方法覆盖非常简单。首先触发自定义ItemCreating事件,然后通过调用基本方法继续。

ItemCreating事件将几个整数传递回用户代码 - 数据源中项目的绝对索引和特定于页面的索引。例如,对于页面大小为10,当ListView正在处理渲染第二页的第一项时,dataItemIndex包含11项,displayIndex包含1项。要使用新的ItemCreating事件,只需在自定义ListView控件上声明方法和处理程序,如下面的代码所示:

<x:ListView runat="server" ID="ListView1" 
   ItemPlaceholderID="itemPlaceholder"
   DataSourceID="ObjectDataSource1"
   OnItemCreating="ListView1_ItemCreating">
   <LayoutTemplate>
      <div>
         <asp:PlaceHolder runat="server" ID="itemPlaceholder" /> 
      </div>
   </LayoutTemplate>
</x:ListView>

在您的代码中,您可以像这样处理事件:

void ListView1_ItemCreating(
     object sender, ListViewItemCreatingEventArgs e)
{
    string url = "standard.ascx";
    if (e.DisplayIndex % DataPager1.PageSize == 0)
        url = "firstItem.ascx";

    ListView1.ItemTemplate = Page.LoadTemplate(url);
}

这里,使用两个不同的用户控件来呈现数据项。特定用户控件由显示索引确定。除第一个项目外,所有项目共享相同的模板。图7显示了正在运行的页面。

当您考虑常见真实网页的复杂性时,此解决方案似乎过于简单。通常,您需要根据要显示的内容使用不同的模板。您需要进一步增强自定义ListView控件以更改数据绑定过程中的项模板。看一下图8中的代码。

图8基于内容选择模板

namespace Samples.Controls
{
  public class ListViewItemCreatingEventArgs : EventArgs
  {
    private int _dataItemIndex;
    private int _displayIndex;

    public ListViewItemCreatingEventArgs(int dataItemIndex,
                                         int displayIndex) {
      _dataItemIndex = dataItemIndex;
      _displayIndex = displayIndex;
    }

    public int DisplayIndex {
      get { return _displayIndex; }
      set { _displayIndex = value; }
    }

    public int DataItemIndex {
      get { return _dataItemIndex; }
      set { _dataItemIndex = value; }
    }
  }

  public class ListView : System.Web.UI.WebControls.ListView
  {
    public event EventHandler<ListViewItemCreatingEventArgs>
     ItemCreating;

    private int _displayIndex;
    private bool _shouldInstantiate = false;

    protected override void InstantiateItemTemplate(Control container,
     int displayIndex) {
      if (_shouldInstantiate) {
        base.InstantiateItemTemplate(container, displayIndex);
        _shouldInstantiate = false;
      }
    }

    protected override ListViewDataItem CreateDataItem(int
     dataItemIndex, int displayIndex) {
      // Fire a NEW event: ItemCreating
      if (ItemCreating != null)
        ItemCreating(this, new
          ListViewItemCreatingEventArgs(dataItemIndex,
          displayIndex));

      // Cache for later
      _displayIndex = displayIndex;

      // Call the base method
      return base.CreateDataItem(_dataItemIndex, displayIndex);
    }

    protected override void OnItemCreated(ListViewItemEventArgs e) {
      base.OnItemCreated(e);

      // You can proceed with template instantiation now
      _shouldInstantiate = true;
      InstantiateItemTemplate(e.Item, _displayIndex);
    }
  }
}

CreateDataItem方法触发ItemCreating事件并缓存显示索引以供以后使用。此外,重写InstantiateItemTemplate方法以延迟实际的模板实例化。私有布尔标志用于此目的。如上所述,ListView在实例化项目模板后启动数据绑定过程。

但是,在图8中的代码所示的实现中,在触发ItemCreated事件之前,实际上没有实例化任何项模板。引发ItemCreated事件时,数据项对象通过DataItem属性绑定到ListView项容器。通过处理代码中的ItemCreated事件,您可以根据绑定数据项决定使用哪个项目模板,如下所示:

protected override void OnItemCreated(ListViewItemEventArgs e)
{
   base.OnItemCreated(e);

   _shouldInstantiate = true;
   InstantiateItemTemplate(e.Item, _displayIndex);
}

在这种情况下,base方法将ItemCreated事件触发到页面。之后,自定义ListView控件重置布尔标志并调用方法来实例化项模板。最后,项目模板比内置的ListView控件稍晚实例化,但是在查看绑定数据项的内容之后,您可以在ItemCreated事件处理程序中以编程方式为每个项设置ItemTemplate属性(请参见图9)。图10显示了一个示例页面,其中蓝色模板用于男性,粉红色模板用于女性。

图9设置项目模板

void ListView1_ItemCreated(object sender, ListViewItemEventArgs e)
{
    // Grab a reference to the data item
    ListViewDataItem currentItem = (e.Item as ListViewDataItem);
    Employee emp = (Employee) currentItem.DataItem;
    if (emp == null)
        return;

    // Apply your logic here
    string titleOfCourtesy = emp.TitleOfCourtesy.ToLower();
    string url = "forgentlemen.ascx";
    if (titleOfCourtesy == "ms." || titleOfCourtesy == "mrs.")
        url = "forladies.ascx";

    // Set the item template to use
    Samples.ListView ctl = (sender as Samples.Controls.ListView);
    ctl.ItemTemplate = Page.LoadTemplate(url);
}