I need to bind an Asp.net DropDownList inside an ItemTemplate of a ListView. I am using LINQ to query data from using the LINQ db context as follow:
.cs
protected void ListView_AllTickets_ItemDataBound(object sender, ListViewItemEventArgs e)
{
DataClassesDataContext db = new DataClassesDataContext();
DropDownList ddl_spList = (DropDownList)e.Item.FindControl("DropDownList_SpList");
//Getting all service providers users
var spusers = (from x in db.User1s where x.usertype == "200" select x);
ddl_spList.DataSource = spusers;
ddl_spList.DataTextField = "email";
ListView_AllTickets.DataBind();
}
.aspx
<asp:DropDownList ID="DropDownList_SpList" runat="server" class="form-control" ClientIDMode="AutoID"> </asp:DropDownList>
Notice how I am finding the control then binding it to the result of the LINQ query. When I use the debugger, the data is retrieved successfully and the "email" field exists in the returned data. However, and for some reason, the ListView_AllTickets will have an item count of 0 even after the DataBind() statment.
You'll need to add this line:
ddl_spList.DataBind();
You're rebinding ListView_AllTickets, but that's the parent object and is already being bound (hence the event you're handling with this method). Is that a typo?
Bind ddl_spList instead.
Related
I desperately seeks in vain. I want to bind a List(T) of Users Controls (.ascx) to a gridview. I initialize my controls in code-behind :
List<myControl> ctrls = new List<myControl>();
myControl ctr = LoadControl("~/Control.ascx") as myControl;
ctr.Name = ...
// ...
ctrls.Add(myControl); // add new control to the collection
And after, i bind this list to Gridview control :
this.GridView1.DataSource = ctrls;
this.gridView1.DataBind();
In the Page_Load event with condition If (!IsPostBack). This does not work: the representation of the object is displayed. Whereas when I put the controls in a Panel, all worked.
Don't use a GridView for this. Use a Repeater. And bind it to the data, not to list of controls. Example:
<asp:Repeater runat="server" id="ControlsRepeater">
<ItemTemplate>
<uc:MyControl runat="server" />
</ItemTemplate>
</asp:Repeater>
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
var myData=GetData(); //should return some type of ICollection representing your data to bind to
ControlsRepeater.DataSource=myData;
ControlsRepeater.DataBind();
}
}
If you want paging, then you should take advantage of lazy loading (the Entity Framework handles this for you if you use that) and the Linq functions .Take() and .Skip().
My web form starts out as two TextBoxes, two Buttons, a CheckBoxList (bound to the results of a database query), and an empty DropDownList.
When the user enters a search phrase into the first TextBox and hits enter (or clicks the first Button, "Search"), a GridView appears, populated with rows pulled from the database. When the user hits the Select button on one of the rows, the DropDownList is populated (bound to results of a database query) and enabled (if the query returned results -- if there were no results, it remains disabled). When the second Button ("Save Settings") is clicked, the relevant data is saved to the DB, the GridView's selection is cleared, and the DropDownList is cleared and disabled.
All of the above works. The problem comes from the DropDownList. I can't get the C# code to recognize the changing SelectedIndex; depending on how I shuffle my code around, the index is always either 0 (and the DropDownList is forced to stay on the first item), or -1 (and the list becomes disabled).
DropDownList code:
<asp:DropDownList ID="myList" runat="server" AutoPostBack="True"
DataTextField="MyName" DataValueField="MyID"
Enabled="False" onselectedindexchanged="myList_SelectedIndexChanged" />
C# code:
protected void myGrid_SelectedIndexChanged(object sender, EventArgs e)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
if (myGrid.SelectedIndex >= 0)
{
int id = int.Parse(myGrid.Rows[myGrid.SelectedIndex].Cells[2].Text);
connection.Open();
string query = "..."; // Omitted for brevity; the query is correct
SqlDataSource source = new SqlDataSource(connectionString, query);
source.SelectParameters.Add("Param1", TypeCode.String, id.ToString());
DataTable dt = ((DataView)source.Select(DataSourceSelectArguments.Empty)).Table;
dt.AcceptChanges();
myList.DataSource = dt;
myList.DataBind();
myList.Enabled = myList.Items.Count != 0;
if (!myList.Enabled)
{
myList.Items.Add(new ListItem("No Results", "0"));
}
}
}
}
protected void myList_SelectedIndexChanged(object sender, EventArgs e)
{
// ((DropDownList)sender).SelectedIndex == -1
}
I've read that there are some problems with DropDownList while searching for a solution to my problem, but besides the note to set AutoPostBack="True", none of the other situations I've found have helped.
One common reason on why the DropDownList loses its SelectedIndex value is, that during the postback is binded again with data. Do you populate data to the DropDownList somewhere else in your code? Maybe there is something else that causes the SelectedIndex event of the GridView to fire again?
Another thought is that changing the Enabled status of the DropDownList might cause this behavior. Try your code without disabling the DropDownList, and see if something changes.
I have an asp.net page which uses a listview to show 2 columns of data.
The first column has just labels and the second one has dropdowns.
My concern is, the dropdowns in second column has same items 100% of the time, they never change and since it is databound, and datasource to these dropdown is also same. As these dropdowns are in a list view this repetition happens on each row added to my list view!
So, I was thinking of removing this data redundancy being transported over the wire. Any ideas?
If you are using an ObjectDataSource, you can reduce the load time enabling the cache:
<asp:objectdatasource ID="ObjectDataSource1" runat="server"
EnableCaching="true" .... >
</asp:objectDataSource>
If your datasource is a database call then you can reduce that by storing the result of the call in a DataView object, and then binding your dropdowns to that object rather than making the call to the database for each dropdown.
You could use the following approach:
It loads the items in to the very first DropDownList and then uses JQuery to retrieve that DropDownList and and replicate the items into all of the others.
Markup
<div id="listViewContainer">
<asp:ListView ID="listView1" runat="server">
<ItemTemplate>
<div><asp:DropDownList ID="dropDownList1" runat="server"></asp:DropDownList></div>
</ItemTemplate>
</asp:ListView>
</div>
Script
$(function () {
var sourceDropDown = $('#listViewContainer').find('select').first();
$('#listViewContainer').find('select').not(sourceDropDown).each(function () {
var dropdown = $(this);
dropdown.find('option').remove();
sourceDropDown.find('option').each(function () {
var option = $(this);
dropdown.append($('<option />').text(option.text()).val(option.val()));
});
});
});
Code
void listView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.DisplayIndex == 0)
{
DropDownList dropDownList1 = (DropDownList)e.Item.FindControl("dropDownList1");
dropDownList1.DataSource = dataTable;
dropDownList1.DataTextField = "Text";
dropDownList1.DataValueField = "Value";
dropDownList1.DataBind();
}
}
Hope this helps.
I have the following scenario:
My page has a dropdown list that allows user to choose a category.
For each category, there is a set of attributes, whose values should be fetched from the user. The number of attributes are different for each category.
Depending on the category the user chooses, a set of dropdown lists should be created corresponding to the attributes and filled with corresponding attribute values.
Since it is required that the page should not reload, I plan to fetch the data (from SQL Server 2008) using AJAX (?). I'm new to ASP.NET and have not used AJAX though I'm comfortable with C#. Need advice on how to proceed.
EDIT: Is this useful if I need to dynamically generate combo boxes?
You can use UpdatePanel or PageMethods
in both cases and in any case, I would say, you do need to know JavaScript when you want to use AJAX and make dynamic web applications. It take some time but it pays off don't worry.
you can search here in SO about PageMethod, for example see this one:
Regarding PageMethod in asp.net
You could use the following approach (if you do not feel comfortable building a more complex UI with javascript).
It works by dynamically creating the attribute DropDownLists when the page loads (you would implement it based on the result of a DB query) and hiding each one, ready for display later on.
Upon the selection of a category the correct DropDownLists would then be made visible (again a query here could determine which attribute DropDownLists become visible).
Obviously it will require some modifications to probably generate a Panel which contains each DropDownList and a Label control, instead of just creating a number of DropDownLists.
You would then show/hide the Panel instead of the DropDownList, but hopefully it points you in the right direction.
Hope this helps.
Markup
<style type="text/css">
select
{
display:block;
margin-top:10px;
}
</style>
....
<asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="updatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<!-- Category selection -->
<asp:DropDownList ID="categoryDropDownList" runat="server" AutoPostBack="true" OnSelectedIndexChanged="categoryDropDownList_SelectedIndexChanged">
<asp:ListItem Text="Please select a category" Value="0"></asp:ListItem>
</asp:DropDownList>
<br />
<!-- Used to store the drop downs -->
<asp:Panel ID="dropDownContainer" runat="server"></asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
Code
protected void Page_Load(object sender, EventArgs e)
{
LoadDropDownLists();
}
private void LoadDropDownLists()
{
//Dummy data, you would pull your categories/attributes from whichever datasource
//you are using
var categories = new[]{
new { Name = "Category 1", Id = 1, Attributes = new string[]{"GA", "FA", "RA"} },
new { Name = "Category 2", Id = 2, Attributes = new string[]{"GA", "NA"} }
};
//Loop through the categories, load the dropdown
foreach (var category in categories)
{
if (!IsPostBack)
categoryDropDownList.Items.Add(new ListItem(category.Name, category.Id.ToString()));
//For each attribute create a drop down and populate with data as required
foreach (var attribute in category.Attributes)
{
string dropDownListId = FormatDropDownListId(attribute);
if (!DropDownListExists(dropDownListId))
{
DropDownList dropDownList = new DropDownList();
dropDownList.ID = dropDownListId;
dropDownList.Visible = false;
dropDownList.Items.Add(new ListItem(attribute));
dropDownContainer.Controls.Add(dropDownList);
}
}
}
}
private bool DropDownListExists(string id)
{
DropDownList dropDownList = (DropDownList)dropDownContainer.FindControl(id);
return dropDownList != null;
}
protected void categoryDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
//Reset all visible dropdowns
HideAllDropDownLists();
//Get the selected category
string selectedItem = categoryDropDownList.SelectedItem.Value;
switch (selectedItem)
{
case "1":
{
//Here you would connect to db and pull correct attributes
//then set the visible dropdowns as required
SetDropDownVisibility(FormatDropDownListId("GA"));
SetDropDownVisibility(FormatDropDownListId("FA"));
SetDropDownVisibility(FormatDropDownListId("RA"));
} break;
case "2":
{
SetDropDownVisibility(FormatDropDownListId("GA"));
SetDropDownVisibility(FormatDropDownListId("NA"));
} break;
}
}
private void SetDropDownVisibility(string id)
{
DropDownList dropDownList = (DropDownList)dropDownContainer.FindControl(id);
if(dropDownList != null)
dropDownList.Visible = true;
}
private void HideAllDropDownLists()
{
foreach (Control control in dropDownContainer.Controls)
{
control.Visible = false;
}
}
private string FormatDropDownListId(string id)
{
return string.Format("dropDown{0}", id);
}
If you're using ASP.NET webforms then I don't believe you need to use AJAX or JavaScript.
I would do the following
Set autopostback = true on your combobox
Add an event handler for the OnChanged event of the combobox
Inside the event handler, apply rules at to load / generate / populate child comboboxes
Add those combo boxes to the form
You can either hide the comboboxes (as I see in #jdavies answer), or start without any and dynamically create & add them to the form.
This question deals with the same issue:
DropDownList and Update Panel
I am developing an application using C#. I am using RadioButtonlist control inside a TreeView. I am getting collection of items from database. Based on the collection items I need to select the Radiobuttonlist items.
For example from the database i got the Collection in this way: Read(R) Write(W)
based on this colletion i need to set up the user permissions.
If I get your question right you want to bind that radiobutton list based on the items in the database based on the current row item on the grid. If thats the case here is your solution.
Lets say you have a Grid called myGrid, a RadioButtonList called myRadio and a HiddenField called myHidden (this is where you bind the value you have on "R" and "W")
All you have to do is when a RowDataBound Event Occurs then you have to assign the value to myRadio
for Example, you have a RadioButtonList like such
<asp:RadioButtonList ID="myRadio" runat="server">
<asp:ListItem Value="R">Read</asp:ListItem>
<asp:ListItem Value="W">Write</asp:ListItem>
</asp:RadioButtonList>
So your code behind should look like this
protected void myGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
RadioButtonList rdoAnswer = (RadioButtonList)e.Row.FindControl("myRadio");
HiddenField hdnValue = (HiddenField)e.Row.FindControl("myHidden");
rdoAnswer.SelectedValue = hdnValue.Value;
}
}