Programmatically Select Item in Asp.Net ListView

38,483

Solution 1

I looked at some of what's going on in ListView under the hood and think this is probably the best approach.

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 )
}

NOTES

  • ListView selects the template an item will use after it's DataBinding event fires. So if the SelectedIndex is set before then, no more work is necessary
  • Setting the SelectedIndex anywhere after DataBinding works, you just don't get the SelectedItemTemplate. For that you have either rebind the data; or reinstantiate the SelectedItemTemplate on the ListViewItem. be sure to clear the ListViewItem.Controls collection first!

UPDATE I have removed most of my original solution, since this should work better and for more cases.

Solution 2

You can set the ListViews SelectedIndex

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

Update

If your loading the data on page load you may have to traverse the data to find the index then set the SelectedIndex value before calling the DataBind() method.

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;
    }
}

Solution 3

list.SelectedIndex = list.Items.IndexOf(item);

Solution 4

Expanding on @Jeremy and @bendewey's answers, you shouldn't need to do this in ItemDataBound. You only need to have the ListView binding already have taken place before you set the SelectedValue. You should be able to do this during PreRender. See this page life cycle docs for more information on when binding takes place.

Share:
38,483
Armstrongest
Author by

Armstrongest

Front end work, Back end work. Cool kids call it the full stack. Ever curious developer of fine web stuff on the internets. "You can't work on the web and not be strive for polyglotism."

Updated on July 05, 2022

Comments

  • Armstrongest
    Armstrongest almost 2 years

    After doing a quick search I can't find the answer to this seemingly simple thing to do.

    How do I Manually Select An Item in an Asp.Net ListView?

    I have a SelectedItemTemplate, but I don't want to use an asp:button or asp:LinkButton to select an item. I want it to be done from a URL. Like a QueryString, for example.

    The way I imagine would be on ItemDataBound, check a condition and then set it to selected if true, but how do I do this?

    For example:

    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!!!
    
            }
         }
      }
    }
    

    I'm sure it's one or two lines of code.

    EDIT: I've updated the code to reflect the solution, and it seems that I can select the ListView's SelectedItemIndex, however, it's not actually rendering the SelectedItemTemplate. I don't know if I should be doing this in the ItemDataBound event as suggested below.

  • Armstrongest
    Armstrongest about 15 years
    Is there an advantage to doing this in PreRender? I usually do these sorts of things in ItemDataBound. I'm also setting the URL of a asp:HyperLink here.
  • Armstrongest
    Armstrongest about 15 years
    Thanks! It seems the second solution might not work: list.SelectedValue = dataItem; (list.SelectedValue is readonly). Using DisplayIndex seems to work, but doesn't change the template for the item. I'm using the sender like so: ((ListView)sender).SelectedIndex = dataItem.DisplayIndex;
  • Armstrongest
    Armstrongest about 15 years
    When I set the SelectedIndex in ItemDataBound it doesn't seem to Take. Does this rely on ViewState?
  • Armstrongest
    Armstrongest about 15 years
    One more comment. I set it like so: ((ListView)sender).SelectedIndex = dataItem.DisplayIndex; but it renders the standard ItemTemplate. Does this rely on ViewState or should I use PreRender? I will go through the Life Cycle Docs now.
  • tuinstoel
    tuinstoel about 15 years
    Also if you need life cycle hang this chart on your cube wall for ref blog.krisvandermast.com/content/binary/…
  • user3788101
    user3788101 about 15 years
    Seems like your going to have to set your SelectedIndex before binding? How and where are you setting the ListView DataSource? Are you using a DataSourceControl? Are you programmatically setting the DataSource and calling DataBind?
  • Nick
    Nick about 15 years
    URL above doesn't work for me. You can download it from Justin's blog, here: spazzarama.wordpress.com/2009/02/04/aspnet-lifecycle
  • Armstrongest
    Armstrongest about 15 years
    I'm setting the DAtaSource in PageLoad. A simple call to my data layer, where I return a List<T>. Then I call DAtaBind(). No DataSourceControl
  • Armstrongest
    Armstrongest about 15 years
    Thanks! I'm going to try this. It seems to most promising solution.
  • Armstrongest
    Armstrongest about 15 years
    Thanks. I'm going through it.
  • Armstrongest
    Armstrongest about 15 years
    Wow! Thanks for all the documentation. Great post! Very elegant solution to reinstantiate the SelectedItemTemplate.