【问题标题】:Programmatically Select Item in Asp.Net ListView以编程方式在 Asp.Net ListView 中选择项目
【发布时间】:2010-10-08 22:04:53
【问题描述】:

快速搜索后,我找不到这个看似简单的事情的答案。

如何在 Asp.Net ListView 中手动选择项目?

我有一个 SelectedItemTemplate,但我不想使用 asp:button 或 asp:LinkBut​​ton 来选择一个项目。我希望从 URL 完成。例如,像 QueryString。

我想象的方式是在 ItemDataBound 上,检查一个条件,然后将其设置为选中,如果为真,但我该怎么做呢?

例如:

protected void lv_ItemDataBound(object sender, ListViewItemEventArgs e) {

  using (ListViewDataItem dataItem = (ListViewDataItem)e.Item) {

     if (dataItem != null) {
        if( /* item select condition */ ) {   

            // What do I do here to Set this Item to be Selected?
            // edit: Here's the solution I'm using :
            ((ListView)sender).SelectedIndex = dataItem.DisplayIndex;

            // Note, I get here and it gets set
            // but the SelectedItemTemplate isn't applied!!!

        }
     }
  }
}

我确定是一两行代码。

编辑:我更新了代码以反映解决方案,似乎我可以选择 ListView 的 SelectedItemIndex,但是,它实际上并没有呈现 SelectedItemTemplate。我不知道我是否应该在 ItemDataBound 事件中执行此操作如下所示

【问题讨论】:

    标签: c# asp.net listview listviewitem selecteditemtemplate


    【解决方案1】:

    我在后台查看了 ListView 中发生的一些事情,并认为这可能是最好的方法。

    void listView_ItemCreated(object sender, ListViewItemEventArgs e)
    {
        // exit if we have already selected an item; This is mainly helpful for
        // postbacks, and will also serve to stop processing once we've found our
        // key; Optionally we could remove the ItemCreated event from the ListView 
        // here instead of just returning.
        if ( listView.SelectedIndex > -1 ) return; 
    
        ListViewDataItem item = e.Item as ListViewDataItem;
        // check to see if the item is the one we want to select (arbitrary) just return true if you want it selected
        if (DoSelectDataItem(item)==true)
        {
            // setting the SelectedIndex is all we really need to do unless 
            // we want to change the template the item will use to render;
            listView.SelectedIndex = item.DisplayIndex;
            if ( listView.SelectedItemTemplate != null )
            {
                // Unfortunately ListView has already a selected a template to use;
                // so clear that out
                e.Item.Controls.Clear();
                // intantiate the SelectedItemTemplate in our item;
                // ListView will DataBind it for us later after ItemCreated has finished!
                listView.SelectedItemTemplate.InstantiateIn(e.Item);
            }
        }
    }
    
    bool DoSelectDataItem(ListViewDataItem item)
    {
        return item.DisplayIndex == 0; // selects the first item in the list (this is just an example after all; keeping it simple :D )
    }
    

    注意事项

    • ListView 选择项目在 DataBinding 事件触发后将使用的模板。因此,如果在此之前设置了 SelectedIndex,则无需进行更多工作
    • 在 DataBinding 工作后的任何位置设置 SelectedIndex,您只是无法获得 SelectedItemTemplate。为此,您要么重新绑定数据;要么或在 ListViewItem 上重新实例化 SelectedItemTemplate。 请务必先清除 ListViewItem.Controls 集合!

    更新我已经删除了大部分我原来的解决方案,因为这应该会更好,适用于更多情况。

    【讨论】:

    • 谢谢!我要试试这个。这似乎是最有希望的解决方案。
    • 哇!感谢所有文档。好帖子!重新实例化 SelectedItemTemplate 的非常优雅的解决方案。
    【解决方案2】:

    您可以设置 ListViews SelectedIndex

    list.SelectedIndex = dataItem.DisplayIndex; // don't know which index you need
    list.SelectedIndex = dataItem.DataItemIndex; 
    

    更新

    如果您在页面加载时加载数据,您可能必须遍历数据以找到索引,然后在调用 DataBind() 方法之前设置 SelectedIndex 值。

    public void Page_Load(object sender, EventArgs e)
    {
      var myData = MyDataSource.GetPeople();
      list.DataSource = myData;
      list.SelectedIndex = myData.FirstIndexOf(p => p.Name.Equals("Bob", StringComparison.InvariantCultureIgnoreCase));
      list.DataBind();
    }
    
    
    public static class EnumerableExtensions
    {
        public static int FirstIndexOf<T>(this IEnumerable<T> source, Predicate<T> predicate)
        {
            int count = 0;
            foreach(var item in source)
            {
                if (predicate(item))
                    return count;
                count++;
            }
            return -1;
        }
    }
    

    【讨论】:

    • 谢谢!似乎第二种解决方案可能不起作用: list.SelectedValue = dataItem; (list.SelectedValue 是只读的)。使用 DisplayIndex 似乎有效,但不会更改项目的模板。我像这样使用发件人: ((ListView)sender).SelectedIndex = dataItem.DisplayIndex;
    • 似乎您必须在绑定之前设置您的 SelectedIndex?您如何以及在哪里设置 ListView 数据源?您使用的是 DataSourceControl 吗?您是否以编程方式设置 DataSource 并调用 DataBind?
    • 我在 PageLoad 中设置数据源。对我的数据层的简单调用,我在其中返回一个 List。然后我调用 DAtaBind()。没有数据源控件
    • 感谢您的更新。一个看起来可行的好解决方案。我将使用所选的解决方案,只是因为它将代码封装到我更喜欢的 ItemCreated 方法中,但是谢谢!
    【解决方案3】:

    扩展@Jeremy 和@bendewey 的答案,您不需要在ItemDataBound 中执行此操作。您只需要在设置 SelectedValue 之前已经发生 ListView 绑定。您应该能够在 PreRender 期间执行此操作。有关何时发生绑定的更多信息,请参阅此页面生命周期 docs

    【讨论】:

    • 在 PreRender 中这样做有优势吗?我通常在 ItemDataBound 中做这些事情。我还在这里设置了一个 asp:HyperLink 的 URL。
    • 还有一条评论。我这样设置: ((ListView)sender).SelectedIndex = dataItem.DisplayIndex;但它呈现标准的 ItemTemplate。这依赖于 ViewState 还是我应该使用 PreRender?我现在将浏览生命周期文档。
    • 另外,如果您需要生命周期,请将此图表挂在立方体墙上以供参考 blog.krisvandermast.com/content/binary/…
    • 上面的网址对我不起作用。你可以从 Justin 的博客下载它,这里:spazzarama.wordpress.com/2009/02/04/aspnet-lifecycle
    • 谢谢。我正在经历它。
    【解决方案4】:
    list.SelectedIndex = list.Items.IndexOf(item);
    

    【讨论】:

    • 当我在 ItemDataBound 中设置 SelectedIndex 时,它似乎没有采取。这是否依赖于 ViewState?
    猜你喜欢
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 2013-12-25
    • 2019-12-17
    • 2011-08-13
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    相关资源
    最近更新 更多