I have this in my page:
<asp:DropDownList ID="membros" runat="server">
</asp:DropDownList>
and in the code behind, I have this:
protected void Page_Load(object sender, EventArgs e)
{
members.Items.Clear();
members.Items.Add(new ListItem("Choose...", ""));
foreach (DataRow item in com.Execute("select * from tableMembers").Rows)
{
members.Items.Add(new ListItem(item["name"].ToString(), item["id_user"].ToString()));
contForeach++;
}
}
and when I try to get the value from SelectedIndex I can't because he always get me 0 independently of what index I choose.
put that in if(!IsPostBack) so that it can load the dropdown at first time the form loads,right now it is loading everytime the page loads so your missing your selection.
if(!IsPostBack)
{
members.Items.Clear();
members.Items.Add(new ListItem("Choose...", ""));
foreach (DataRow item in com.Execute("select * from tableMembers").Rows)
{
members.Items.Add(new ListItem(item["name"].ToString(), item["id_user"].ToString()));
contForeach++;
}
}
Apart from the IsPostBack mentioned, you should be doing it this way instead of looping through the data
Modify your markup
<asp:DropDownList ID="membros" runat="server" DataTextField="name" DataValueField="user_id">
From code behind, bind the data
if(!IsPostBack)
{
DataTable dt = com.Execute("select * from tableMembers");
members.DataSource = dt;
members.DataBind();
members.Items.Insert(0, new ListItem("Choose...", ""));
}
Bound controls like DropdownList, GridView, DataList etc have DataSource property that you can use to assign a collection to them and they would loop through it and extract the data.
Related
IN dot net, User control has a drop down when it is changed. The grid needs to be changed, but the grid is not inside user control?
How can we achieve it?
You bind an event using the OnSelectedIndexChange to your drop down list on your aspx page:
<asp:DropDownList ID="ddlGridType" runat="server" OnSelectedIndexChanged="ddlGridType_SelectedIndexChanged" AutoPostBack="true" >
Then on your C# code behind:
protected void ddlRunType_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dtblDataSource = New DataTable();
string gridType = ddlGridType.SelectedValue;
//remove the old data from the grid view
TheGridView.DataSource = null;
TheGridView.DataBind();
//get the new data using whatever method you use to get the data
dtblDataSource = theGridView_GetDataSource(gridType);
//bind the new data to the list
TheGridView.DataSource = dtblDataSource;
TheGridView.DataBind();
}
how do you properly call methods inside custom binding expressions? Are there complications because the dropdownlist is inside a detailsview?
asp.net code:
<asp:DropDownList ID="ddlExceptionEditStatus" runat="server"
DataSourceID="odsExceptionsStatus"
DataTextField="Name"
DataValueField="StatusID"
SelectedValue='<%# Bind("StatusID") %>'
BackColor="<%# SetBackColorProp(Container.DataItem) %>">
</asp:DropDownList>
code behind:
protected System.Drawing.Color SetBackColorProp(object o)
{
System.Drawing.Color statusColor = System.Drawing.Color.White;
string statusName = o as string;
if (statusName != null)
{
statusColor = System.Drawing.ColorTranslator.FromHtml(FISBLL.StatusColors.GetColor(statusName));
return statusColor;
}
else
{
return statusColor;
}
}
Doesn't change the backcolor. but doesn't throw an exception.
So, I had two mistakes:
1) I needed to cast the Container.DataItem to the class object i was using for the ObjectDataSource. After casting, the BackColor for each item in the dropdownlist matched the StatusID of the casted Container.DataItem.
2) Unfortunately this gave all the items the same color, where as I wanted each item's color to reflect the their own value attached to the dropdownlist. This is because the dropdownlist has an objectdatasource outside the DetailsView that it's inside of. Therefor the selectedValue item of the dropdownlist dictated the colors for all the other items.
I decided to go with Tim's suggestion and tie the BackColor setting for each item in the databound event:
protected string GetColor(string name)
{
return FISBLL.StatusColors.GetColor(name);
}
protected void ddlExceptionEditStatus_DataBound(object sender, EventArgs e)
{
foreach (ListItem item in ((DropDownList)sender).Items)
{
item.Attributes.Add("style", "background-color:" + GetColor(item.Text));
}
}
And the correct behavior is shown:
i had a DataList view which i add a check box in the Item Template
i want each item i select to increase some counter for examble once it's checked ..
i used the following code to handle that ,but the event function is never accessed ?!
protected void selectItemCheckBox_CheckedChanged(object sender, EventArgs e)
{
int selected = 0;
foreach (DataListItem i in DataList1.Items)
{
CheckBox chk = (CheckBox)i.FindControl("selectItemCheckBox");
if (chk.Checked)
{
selected++;
}
selectedItemCount.Text = Convert.ToString(selected);
}`
}
Currently you're looping over every checkbox for every checked checkbox which is inefficient and depending on your other code, may be causing trouble.
You're better off incrementing for each checkbox individually.
...DataList...
<ItemTemplate>
<asp:CheckBox id="selectItemCheckBox" runat="server"
AutoPostBack="True"
OnCheckedChanged="selectItemCheckBox_CheckedChanged" />
</ItemTemplate>
...DataList...
After a box is checked, update the total for just that checkbox using sender
protected void selectItemCheckBox_CheckedChanged(object sender, EventArgs e)
{
// Parse the total selected items from the TextBox.
// You may consider using a Label instead, or something non-editable like a hidden field
int totalChecked;
if (int.TryParse(selectedItemCount.Text, out totalChecked) = false)
totalChecked = 0;
// Get a reference to the CheckBox
CheckBox selectItemCheckBox = (CheckBox)sender;
// Increment the total
if (selectItemCheckBox.Checked == true)
totalChecked++;
// Put back in the TextBox
selectedItemCount.Text = totalChecked.ToString();
}
I have a GridView and a select link in the GrdiView, when the item is selected I want it to read the contents to a textbox below the GridView. The only way I can think is by accessing the behind code for the onClick function of the select link. The problem is I am unsure how to do this.
UPDATED jams method:
C# code
protected void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
GridView1.SelectedIndex = e.NewSelectedIndex;
TextBox1.Text = GridView1.Rows[e.NewSelectedIndex].Cells[0].Text;
}
front code
<asp:GridView ID="GridView1" OnSelectedIndexChanging="GridView1_SelectedIndexChanging" runat="server" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333"
GridLines="None">
UPDATE my method:
protected void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
int i = GridView1.SelectedIndex;
ds.Tables["Comments"].Rows[i]["Comment"] = TextBox1.Text;
}
also tried this but I get an error -> System.IndexOutOfRangeException: There is no row at position -1.
Thanks.
You need to attach OnSelectedIndexChanged event with your gridview
<asp:GridView OnSelectedIndexChanged="GridView1_SelectedIndexChanged" />
Then in code behind you could do:
void GridView1_SelectedIndexChanged(Object sender, EventArgs e)
{
GridViewRow row = CustomersGridView.SelectedRow;// you will get the selected row
someLabel.Text = row.Cells[0].Text;
}
Once you attach to the selectedindexchanged event you need to also set up some datakeys so you can retrieve values from your grid. See sample here.
void CustomersGridView_SelectedIndexChanged(Object sender, EventArgs e)
{
// Determine the index of the selected row.
int index = CustomersGridView.SelectedIndex;
// Display the primary key value of the selected row.
Message.Text = "The primary key value of the selected row is " +
CustomersGridView.DataKeys[index].Value.ToString() + ".";
}
it is better to use oORowCommand event of the grid view and pass the command argument and commandName to the same event as a attribute value. Then i think it will work.
I have a page with a table of stuff and I need to allow the user to select rows to process. I've figured out how to add a column of check boxes to the table but I can't seem to figure out how to test if they are checked when the form is submitted. If they were static elements, I'd be able to just check do this.theCheckBox but they are programaticly generated.
Also I'm not very happy with how I'm attaching my data to them (by stuffing it in there ID property).
I'm not sure if it's relevant but I'm looking at a bit of a catch-22 as I need to known which of the checkboxes that were created last time around were checked before I can re-run the code that created them.
Edit:
I've found an almost solution. By setting the AutoPostBack property and the CheckedChanged event:
checkbox.AutoPostBack = false;
checkbox.CheckedChanged += new EventHandler(checkbox_CheckedChanged);
I can get code to be called on a post back for any check box that has changed. However this has two problems:
The call back is processed after (or during, I'm not sure) Page_Load where I need to use this information
The call back is not called for check boxes that were checked when the page loaded and still are.
Edit 2:
What I ended up doing was tagging all my ID's with a know prefix and stuffing this at the top of Form_Load:
foreach (string v in this.Request.Form.AllKeys)
{
if (v.StartsWith(Prefix))
{
var data = v.Substring(Prefix.Length);
}
}
everything else seems to run to late.
I'm going to assume you're using a DataList but this should work with and Control that can be templated. I'm also going to assume you're using DataBinding.
Code Front:
<asp:DataList ID="List" OnItemDataBound="List_ItemDataBound" runat="server">
<ItemTemplate>
<asp:CheckBox ID="DeleteMe" runat="server"/>
<a href="<%# DataBinder.Eval(Container, "DataItem.Url")%>" target="_blank">
<%# DataBinder.Eval(Container, "DataItem.Title")%></a>
</ItemTemplate>
</asp:DataList>
<asp:Button ID="DeleteListItem" runat="server" OnClick="DeleteListItem_Click" ></asp:Button>
Code Behind:
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadList();
}
protected void DeleteListItem_Click(object sender, EventArgs e)
{
foreach (DataListItem li in List.Items)
{
CheckBox delMe = (CheckBox)li.FindControl("DeleteMe");
if (delMe != null && delMe.Checked)
//Do Something
}
}
LoadList();
}
protected void LoadList()
{
DataTable dt = //Something...
List.DataSource = dt;
List.DataBind();
}
protected void List_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
string id = DataBinder.Eval(e.Item.DataItem, "ID").ToString();
CheckBox delMe = (CheckBox)e.Item.FindControl("DeleteMe");
if (delMe != null)
delMe.Attributes.Add("value", id);
}
}
}
First, make sure that each Checkbox has an ID and that it's got the 'runat="server"' in the tag.
then use the FindControl() function to find it.
For example, if you're looping through all rows in a GridView..
foreach(GridViewRow r in Gridview1.Rows)
{
object cb = r.FindControl("MyCheckBoxId");
if(r != null)
{
CheckBox chk = (CheckBox)cb;
bool IsChecked = chk.Checked;
}
}
Postback data is restored between the InitComplete event and the PreLoad event. If your checkboxes are not created until later then the checkboxes will play "catch up" with their events and the data will be loaded into the control shortly after it is created.
If this is to late for you then you will have to do something like what you are already doing. That is you will have to access the post data before it is given to the control.
If you can save the UniqueId of each CheckBox that you create then can directly access the post data without having to given them a special prefix. You could do this by creating a list of strings which you save the ids in as you generate them and then saving them in the view state. Of course that requires the view state to be enabled and takes up more space in the viewstate.
foreach (string uniqueId in UniqueIds)
{
bool data = Convert.ToBoolean(Request.Form[uniqueId]);
//...
}
Your post is a little vague. It would help to see how you're adding controls to the table. Is it an ASP:Table or a regular HTML table (presumably with a runat="server" attribute since you've successfully added items to it)?
If you intend to let the user make a bunch of selections, then hit a "Submit" button, whereupon you'll process each row based on which row is checked, then you should not be handling the CheckChanged event. Otherwise, as you've noticed, you'll be causing a postback each time and it won't process any of the other checkboxes. So when you create the CheckBox do not set the eventhandler so it doesn't cause a postback.
In your submit button's eventhandler you would loop through each table row, cell, then determine whether the cell's children control contained a checkbox.
I would suggest not using a table. From what you're describing perhaps a GridView or DataList is a better option.
EDIT: here's a simple example to demonstrate. You should be able to get this working in a new project to test out.
Markup
<form id="form1" runat="server">
<div>
<table id="tbl" runat="server"></table>
<asp:Button ID="btnSubmit" runat="server" Text="Submit"
onclick="btnSubmit_Click" />
</div>
</form>
Code-behind
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
var row = new HtmlTableRow();
var cell = new HtmlTableCell();
cell.InnerText = "Row: " + i.ToString();
row.Cells.Add(cell);
cell = new HtmlTableCell();
CheckBox chk = new CheckBox() { ID = "chk" + i.ToString() };
cell.Controls.Add(chk);
row.Cells.Add(cell);
tbl.Rows.Add(row);
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
foreach (HtmlTableRow row in tbl.Rows)
{
foreach (HtmlTableCell cell in row.Cells)
{
foreach (Control c in cell.Controls)
{
if (c is CheckBox)
{
// do your processing here
CheckBox chk = c as CheckBox;
if (chk.Checked)
{
Response.Write(chk.ID + " was checked <br />");
}
}
}
}
}
}
What about using the CheckBoxList control? I have no Visual Studio open now, but as far as I remember it is a DataBound control, providing DataSource and DataBind() where you can provide a list at runtime. When the page does a postback you can traverse the list by calling something like myCheckBoxList.Items and check whether the current item is selected by calling ListItem.Selected method. This should work.
Add them in an override of the CreateChildControls method of the Page. Be sure to give them an ID! This way they get added to the control tree at the correct time.
IMHO The best way would be to use DataBound Templated Control though, i.e. something like a ListView (in .NET 3.5). then in pageload after postback traverse all items in the databound control and use item.FindControl to get at the actual checkbox.
What I ended up doing was tagging all my ID's with a know prefix and stuffing this at the top of Form_Load:
foreach (string v in this.Request.Form.AllKeys)
{
if (v.StartsWith(Prefix))
{
var data = v.Substring(Prefix.Length);
}
}
everything else seems to run to late.