I have a databound ListView in asp.Net. I have both ItemTemplate and SelectedItemTemplate used in the aspx page.
In the .cs page I have this. I have verified by stepping through the code that the if statement evaluates to true only when it is supposed to, and that the selected index is set. However the HTML output is as if all items use the ItemTemplate.
int indexCounter = 0;
protected void lvProducts_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
if (((DataRowView)e.Item.DataItem)["ID"].ToString() == Request.QueryString["id"])
{
lvProducts.SelectedIndex = indexCounter;
}
indexCounter++;
}
}
Is there a better way to do this?
check out this post
"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!"
Related
I have a MasterDetailsView on a page which I'm navigating to from another page. I pass in an argument which corresponds to an item in the list the MasterDetailsView is bound to as the ItemSource, like this:
protected override void OnNavigatedTo(NavigationEventArgs e) {
if (e.Parameter != null) {
Thing selectedThing = e.Parameter as Thing;
Selected = selectedThing;
MasterDetailsViewControl.SelectedItem = selectedThing;
}
}
This works fine on form factors with large screens - the DetailsView populates successfully with the relevant content. However, on smaller screens, the DetailsView is hidden in favour of the ListView being full screen. This is normally advantageous, but here I want to have the DetailsView open, as an individual Thing has just been deep linked to.
Seeing as the ViewState property of a MasterDetailsView is read-only, is there some way to force the DetailsView open rather than the ListView on these smaller screens? If not, how should one go about facilitating that deep linking functionality?
With my testing, When the MasterDetailsView control has not been loaded, if you set the SelectedItem property, it will not fire the OnSelectedItemChanged handler. That's the reason why the DetailsView will not open.
To solve your question, you could set the SelectedItem in MasterDetailsViewControl's Loaded event handler.
private Thing Selected;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.Parameter != null)
{
Thing selectedThing = e.Parameter as Thing;
Selected = selectedThing;
}
}
private void MasterDetailsViewControl_Loaded(object sender, RoutedEventArgs e)
{
MasterDetailsViewControl.SelectedItem = Selected;
}
I am trying to use two DropDownLists to filter data. I set both of the OnSelectedIndexChanged Equal to the method below. The problem is it is only grabbing the SelectedIndex of the DDL that is changed. Example: if i choose a option in DDL1 it grabs that value and doesnt grab the value of DDL2. They both have the same OnSelectedIndexChanged i figured it would grab the current value of both. Is there a way to make it look at both DDL Controls?
protected void BrandsList_SelectedIndexChanged(object sender, EventArgs e)
{
int DDLcatId = CategoriesList.SelectedIndex;
int DDLBraId = BrandsList.SelectedIndex;
IQueryable<Product> DDLprodResult = GetProductsDDL(DDLcatId, DDLBraId);
if(DDLprodResult == null)
{
}
else
{
CatLab.Text = DDLprodResult.ToList().Count().ToString();
productList.DataSource = DDLprodResult.ToList();
productList.DataBind();
}
}
Your code should work. Of course only one can be changed if you have set AutoPostBack="true"(default is false) on both. But you should get the correct SelectedIndex anyway in the handler.
So i will guess: you are databinding the DropDownLists on every postback. Do this only if(!IsPostBack), otherwise you always overwrite changes with the original values.
So for example in Page_Load:
protected void Page_Load(Object sender, EvengtArgs e)
{
if(!IsPostBack)
{
// DataBind your DropDownLists
}
}
I have an asp.net dropDownList which is automatically bound to a sqlDataSource to values of client type on page load. On page load I am also creating a Client object, one of it's properties is ClientType. I am trying to set the SelectedValue of the ddl according to the value of the ClientType property of the Client object unsuccessfully. I recieve the following error message "System.ArgumentOutOfRangeException: 'ddlClientType' has a SelectedValue which is invalid because it does not exist in the list of items". I understand that this is because the list has not yet been populated when I'm trying to set the selected value. Is there a way of overcoming this problem? Thank you!
You have to use the DataBound Event, it will be fired, once databinding is complete
protected void DropDownList1_DataBound(object sender, EventArgs e)
{
// You need to set the Selected value here...
}
If you really want to see the value in the Page load event, then call the DataBind() method before setting the value...
protected void Page_Load(object sender, EventArgs e)
{
DropdownList1.DataBind();
DropdownList1.SelectedValue = "Value";
}
Before setting a selected value check whether item is in list and than select it by index
<asp:DropDownList id="dropDownList"
AutoPostBack="True"
OnDataBound="OnListDataBound"
runat="server />
protected void OnListDataBound(object sender, EventArgs e)
{
int itemIndex = dropDownList.Items.IndexOf(itemToSelect);
if (itemIndex >= 0)
{
dropDownList.SelectedItemIndex = itemIndex;
}
}
EDIT: Added...
If you are doing binding stuff in Page Load, try to follow this way:
Move all binding related code in overriden DataBind() method
In Page_Load of Page add: (in case of control do not call DataBind directrly, this is a responsibility of a parent page)
if (!IsPostBack)
{
Page.DataBind(); // only for pages
}
I have a ListView with a template, it puts a bunch of data in, like X Y Z.
I want to hide show some columns based on criteria, so I have ItemDataBound event, but I don't know how to get the actual listview row so I can do things to do it.
Any ideas?
You can access the ListViewItemEventArgs' Item property to get at the current item (the one being bound to data).
The sample code below (which shows how to customize a ListView item in the ItemDataBound event) was taken from the MSDN documentation:
protected void ContactsListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
Label EmailAddressLabel;
if (e.Item.ItemType == ListViewItemType.DataItem)
{
// Display the e-mail address in italics.
EmailAddressLabel = (Label)e.Item.FindControl("EmailAddressLabel");
EmailAddressLabel.Font.Italic = true;
System.Data.DataRowView rowView = e.Item.DataItem as System.Data.DataRowView;
string currentEmailAddress = rowView["EmailAddress"].ToString();
if (currentEmailAddress == "orlando0#adventure-works.com")
{
EmailAddressLabel.Font.Bold = true;
}
}
}
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.
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.
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;
}
}
list.SelectedIndex = list.Items.IndexOf(item);
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.