Dropdownlist in repeater control - asp.net

I have 3 dropdownlist which will have set of values from the database. In my page, I have different controls. I was planning to add this dropdownlist in a repeater control.
When a user selects a value, the value will be saved to the database, either by a save button inside the control or automatically.
Could you please let me know if this is possible? If yes, any code that can be shared would be helpful.

Yes, it's possible. The trick is that the DataSource for the dropdownlists are separate than the DataSource of the Repeater.

Here's the sample code:
protected void cmdSave_Click(object sender, EventArgs e)
{
foreach (RepeaterItem ri in GeneralRepeater.Items)
{
switch (ri.ItemType)
{
case ListItemType.Item:
case ListItemType.AlternatingItem:
DropDownList GetValue = (DropDownList)ri.FindControl("GeneralDDL");
var sSelectedValue = GetValue.SelectedValue;
for (int index = 0; index <= PocDiagnoses.MAX_DIAGNOSIS; index++)
{
foreach (RepeaterItem ri1 in GeneralRepeater.Items)
{
int iItemIndex = ri1.ItemIndex;
DropDownList myDDL = (DropDownList)GeneralRepeater.Items[index].FindControl("GeneralDDL");
FirstPlanOfCare.Diagnoses.Diagnoses[index] = new PatientDiagnosis(myDDL.SelectedValue, new SynergyOnSetDate(new System.DateTime(Year, Month, Day)), "01/02/2011"); //Insert Diagnosis Value
}
}
break;
}
}
//Create
Chart.AddPlanOfCare(FirstPlanOfCare);
}

Related

Unable to load Controls from Empty Data Template in GridView asp.net

I have a GridView which is binded with DataTable for the datasource, when there is no records in the underlying datasource i show up the EmptyDataTemplate with Two DropDown (State and City) and based on the State i fills up City.
Now my problem is till i have some records inside the Datasource it works fine, but as soon as i delete the last remaining record from the datasource, it throws error, it switches to the emptydatatemplate but it could not find the States Dropdownlist (based on which i am filling city dropdown). But once i refresh the page it works fine.
I don't understand which event to grab to place the codes
Here's what i am doing
Below function gets the stateid and fills the cities based on it
private void FillCitiesByStateId()
{
drpCity = grdLocationView.Controls[0].Controls[0].FindControl("drpCitiesAdd") as DropDownList;
drpState = grdLocationView.Controls[0].Controls[0].FindControl("drpStatesAdd") as DropDownList; // Fetches the States DropDown from EmptyDataTemplate.
if (drpState != null)
{
objCity.StateId = Convert.ToInt32(drpState.SelectedValue); //It always throws error on this line.
drpCity.DataSource = objCity.GetCitiesByStateId();
drpCity.DataTextField = "Name";
drpCity.DataValueField = "Id";
drpCity.DataBind();
}
}
Below is the code i which is used to bind the records in dropdowns
protected void grdLocationView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (dt.Rows.Count == 0)
{
FillCitiesByStateId();
}
else
{
if (e.Row.RowType == DataControlRowType.Header)
{
drpCity = e.Row.FindControl("drpCities") as DropDownList;
drpState = e.Row.FindControl("drpStates") as DropDownList;
objCity.StateId = Convert.ToInt32(drpState.SelectedValue);
drpCity.DataSource = objCity.GetCitiesByStateId();
drpCity.DataTextField = "Name";
drpCity.DataValueField = "Id";
drpCity.DataBind();
}
}
}
Can anyone provide any suggestion whats going wrong with it
Make sure you are only calling the FillCitiesByStateId() for appropriate row types. Maybe you're calling it for a footer row?
DataControlRowType Enumeration
instead of:
if (dt.Rows.Count == 0)
{
FillCitiesByStateId();
}
try:
if (e.Row.RowType == DataControlRowType.EmptyDataRow)
{
FillCitiesByStateId();
}

accessing selected checkboxes in gridview

i have a gridview in which i am using checkbox in each row. i am trying to access checkbox of each row and trying to find out which checkboxes have been checked.buut when i try to run the below code.the condition always stands to be false and the inner if condition is never reached by the code.kindly help me.thanks in advance.
protected void btn_3id_Click(object sender, EventArgs e)
{
string str = "";
string srr = "";
for (int i = 0; i < GridView1.Rows.Count;i++ )
{
CheckBox chk = (CheckBox)GridView1.Rows[i].FindControl("CheckBox1");
if (chk.Checked==true)
{
if (str == "")
{
str = GridView1.Rows[i].Cells[0].Text.ToString();
}
else
{
srr = str + "," + GridView1.Rows[i].Cells[0].Text.ToString();
}
}
}
Session["Card_id"] = str;
Response.Redirect("ID.aspx");
}
The code looks fine.
The problem could be you are binding the gridview at page load.
Try grid binding in the following section of page load
if(!Page.IsPostBack)
{
//code to bind the gridview
}
I can only guess that you are binding your gridview on each page load without checking PostBack. That is causing the checkbox to loose its current state. So where you are assigning the DataSource to the Gridview , Check for PostBack like:
if(!Page.IsPostBack)
{
GridView1.DataSource = yourDataSource;
GridView1.DataBind();
}
also you can do some minor improvements in your code like your check:
if(chk.Checked == true)
can be replaced as:
if(chk.Checked) //Since it returns a bool value.
You can omit multiple string variables for concatenation. Its better if you use StringBuilder, (See why it is better) so your code would be:
protected void btn_3id_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < GridView1.Rows.Count;i++ )
{
CheckBox chk = (CheckBox)GridView1.Rows[i].FindControl("CheckBox1");
if (chk.Checked==true)
{
sb.Append() GridView1.Rows[i].Cells[0].Text.ToString();
}
}
Session["Card_id"] = sb.ToString();
Response.Redirect("ID.aspx");
}
if(!Page.IsPostBack)
{
//
}
Postback plays important role in cs file. If you are clearing values on page load , you will null values of checkbox.
You code is fine.
Just try to do this...

Get control which is generated on runtime

am creating some TextBoxes by backend on a text change event, Like this :
protected void txtHowMany_TextChanged(object sender, EventArgs e)
{
int totalSections = Convert.ToInt32(txtHowMany.Text.Trim());
for (int i = 1; i <= totalSections; i++)
{
TextBox tbx = new TextBox();
tbx.Text = "";
tbx.ID = "section" + i;
tbx.Style.Add("width", "90%");
tdSectionsAdd.Controls.Add(tbx);
}
trSectionsName.Visible = true;
}
The auto post back is true for txtHowMany, so when I enter a number, it generates the textboxes and add it to table division
Now the problem is, I am trying to get text from generated textboxes like this :
protected void btnSave_click(object sender, EventArgs e)
{
int numbersOfSectionsToSave = 1;
int sectionsToSave =Convert.ToInt32(txtHowMany.Text.Trim());
for (int i = 1; i < sectionsToSave; i++)
{
Sections section = new Sections();
section.CourseId = result;
section.OrganizationId = course.OrganizationId;
foreach (Control c in tdSectionsAdd.Controls)
{
if (c.GetType() == typeof(TextBox))
{
TextBox txtBox = (TextBox)c;
string id = "section" + i;
if (txtBox.ID == id)
{
section.Name = txtBox.Text.Trim();
}
}
}
string name = Request.Form["section1"];
section.CreatedBy = "Admin";
section.CreationDate = DateTime.Now;
section.ModifiedBy = "Admin";
section.ModificationDate = DateTime.Now;
numbersOfSectionsToSave += section.SaveSection();
}
But its showing 0 count for the controls in tdSectionsAdd , The controls are added before I am trying to access them, but still it shows no controls in td.
Please help, How can I get these textboxes?
Thanks!
You need to add them in each postback. Store the totalSections variable in ViewState so you can add them i page load also:
protected void AddTextBoxes()
{
int totalSections;
if (int.TryParse(Convert.ToString(ViewState["TotalSections"]), out totalSections)
{
for (int i = 1; i <= totalSections; i++)
{
TextBox tbx = new TextBox();
tbx.Text = "";
tbx.ID = "section" + i;
tbx.Style.Add("width", "90%");
tdSectionsAdd.Controls.Add(tbx);
}
trSectionsName.Visible = true;
}
}
protected void txtHowMany_TextChanged(object sender, EventArgs e)
{
ViewState["TotalSections"] = Convert.ToInt32(txtHowMany.Text.Trim());
tdSectionsAdd.Controls.Clear();
AddTextBoxes();
}
protected void Page_Load(object sender, EventArgs e)
{
AddTextBoxes();
}
Dynamic Created controls "Disappear" on postback, if they are not "recreated" in the Page_Init of that page.
Only if they are created in the page_init will the page's viewstate get updated with their information.
Long Explantion:
When we perform a postback (or partial postback) we want to be able to access those controls (or at least the values the user put into them).
We know that the data is in the viewstate, but ASP.NET doesn’t really know which control a ViewState item belongs to. It only knows to match a viewstate item and a control through the same index (e.g. Matches item n in the viewstate tree to item n in the control tree). Therefore in order to get the dynamic controls' data, we need to re-create the controls each time the page is postbacked.
BUT in order for this to work, we need to re-create the controls in the Page_Init function NOT in the Page_Load.
Why? Because when the ViewState is created it needs all the controls to already exist.
This is taken from MSDN, as you can see the viewstate is loaded AFTER the init but before the page load.
TL;DR Call the function that creates the dynamic controls in the page_init and you should be able to see all the values the user entered when the page postbacks
A few links on this issue:
http://forums.asp.net/t/1186195.aspx/1
ASP.NET - Dynamic controls created in Page_Pre_init() or Page_Init() or Page_Load()
Option 2:
I should note: If the controls all had unique Ids and you're not interested in re-creating them again every postback - you could always look for them in the Request Object.
The Request.Form is a NameValueCollection that holds the values of all the controls that were part of the form, just search it for whatever you're looking for

ASPxCombobox not fetched from SQLdatasource saved in session

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Session["SavedSQLSources"] == null)
SavedSQLSources = new Dictionary<String, SqlDataSource>();
SavedSQLSources.Add(ASPxComboBox1.ID, SqlDataSource1);
SavedSQLSources.Add(ASPxComboBox2.ID, SqlDataSource2);
Session["SavedSQLSources"] = SavedSQLSources;
}
else
{
if (Session["SavedSQLSources"] != null)
SavedSQLSources = (Dictionary<String, SqlDataSource>)Session["SavedSQLSources"];
}
}
Greetings, I have multiple ASPxCombobox with each having their own datasource. So first I saved
each control ID with their corresponding datasource object in a dictionary.
protected void Cmb_Callback(object source, CallbackEventArgsBase e)
{
ASPxComboBox comboBox = (ASPxComboBox)source;
string[] args = e.Parameter.Split('|');
for (int i = 0; i < args.Length; ++i)
SavedSQLSources[comboBox.ID].SelectParameters[i].DefaultValue = args[i];
comboBox.DataSourceID = SavedSQLSources[comboBox.ID].ID;
comboBox.DataBind();
}
Doing a few actions on the page, each control then launch its callback and bind its data with the corresponding datasource.
Well... Work perfectly when using directly the datasource, but having no items fetched when it's from a datasource saved in Session (from SavedSQLSources).
Shouldn't the instance of the object be the same ?
Thanks in advance, TheRainFall.
Ok, I gave up on the dictionnary method and resolved this by linking each ASPxCombobox to its SqlDatasource from client-side:
DataSourceID="SqlDataSource1"
Then in the callback I got the sqldatasource instance from the parent container by using the datasourceID referenced from client-side:
SqlDataSource tempSqlDatasource= (SqlDataSource)comboBox.Parent.FindControl(comboBox.DataSourceID);
The main purpose was to reload all combobox without reloading the page although I could have done this client-side only.

Dynamically created rows disappear from Gridviews on update/delete

Situation: I have several Gridviews on one page, and each Gridview has a dynamically created row to display the totals at the bottom. In each case, the totals row is created on a RowDataBound event. The strategy that I am using is like the one provided by Mike Dugan on his Blog.
The following is the code for one of the GridViews, but the others all do something very simular.
protected void gvWorkerHours_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Keep running total of hours.
if (e.Row.RowType == DataControlRowType.DataRow)
{
totalBillableHours += Convert.ToDouble(DataBinder.Eval(e.Row.DataItem, "Hours"));
}
if (e.Row.RowType == DataControlRowType.Footer)
{
int numColumns = gvWorkerHours.Columns.Count;
int hoursIndex = 4; //5th column, 0-based
int rowIndex = gvWorkerHours.Rows.Count + 1;
CreateTotalRow((Table)e.Row.Parent, rowIndex, totalBillableHours, hoursIndex, numColumns);
}
}
private void CreateTotalRow(Table table, int rowIndex, double totalValue, int totalIndex, int numColumns)
{
TableCell[] cells = new TableCell[numColumns];
for (int i = 0; i < numColumns; i++)
{
TableCell cell = new TableCell();
Label label = new Label();
label.Font.Bold = true;
if (i == 0)
{
label.Text = "Total";
}
else if (i == totalIndex)
{
label.Text = totalValue.ToString();
}
else
{
label.Text = "";
}
cell.Controls.Add(label);
cells[i] = cell;
}
GridViewRow row = new GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal);
row.Cells.AddRange(cells);
table.Rows.AddAt(rowIndex, row);
}
Problem: If a user clicks on an edit/delete command for any row on any of these Gridviews, it will make the totals row disappear for all other Gridviews. As I understand, this is because a PostBack is occurring, however the RowDataBound events will not occur for the other GridViews, rather they will just reload their data from the ViewState, which does not contain the totals.
Failed attempts at solving: I cannot simply call DataBind on each of the GridView during a PostBack, because that will prevent the update/delete from occurring. Although the RowCreated event will occur for the GridViews during a PostBack, this event in not sufficient because the GridViews will not have data bound and will throw an exception when I try to calculate the total. Disabling the ViewState for these GridViews seems like a solution, however there will be a lot of data to reload each time a user clicks a command. Manually saving my data to the ViewState also seems like a solution, but there does not seem to be a simple way to have the GridViews retrieve this custom data on a PostBack.
Is there any way to actually achieve what I am trying to do with ASP.NET? It seems like a simple requirement to have a totals row at the bottom of each GridView.
Thanks in advance for any help.
What if you try creating the dynamic row using the gridView.OnPreRender event instead of the gridView.RowDataBound event. This way your data you need to calculate your dynaimic row results is available but the html has not been sent to the web browser yet. Please post some more code so we can provide more insight into fixing your issue.
As recommended, I tried putting the code to create the totals row in the PreRender event rather than the RowDataBound event. This seemed to work, except that it broke all of the commands for the GridView that it was used on. It appears that manually changing the GridView disrupts its automatic behavior.
protected void gvWorkerHours_PreRender(object sender, EventArgs e)
{
double total = 0;
int numColumns = gvWorkerHours.Columns.Count;
int hoursIndex = 4; //5th column, 0-based
int rowIndex = gvWorkerHours.Rows.Count + 1;
foreach (GridViewRow row in gvWorkerHours.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
Label label = (Label)row.FindControl("lblHours");
total += Convert.ToDouble(label.Text);
}
}
CreateTotalRow((Table)gvWorkerHours.Rows[0].Parent, rowIndex, total, hoursIndex, numColumns);
}
OK, the way I ended up solving this was with JQuery. If anybody else is facing a similar problem, remember that the totals must be calculated when the DOM is ready, as well as at the end of any postback. To handle the postback situation, you can just call the Javascript on the client using ScriptManager.RegisterStartupScript().
Again, I had four GridViews in my circumstance, but I'll just show the JQuery code for one of them:
$(document).ready(function () {
setTotals();
});
function setTotals() {
var totalHours = getBillableHoursTotal();
if (isNaN(totalHours)) totalHours = '...editing';
$('#spanBillableHoursTotal').html(totalHours);
//... etc.
}
function getBillableHoursTotal() {
var total = 0.0;
var rows = $('table[id*="_gvWorkerHours"] tr.RegularRows');
$(rows).each(function () {
total = total + parseFloat($(this).children('td').children('span[id*="lblHours"]').html());
});
return total;
}
And for the C# on the code behind:
protected void Page_Load(object sender, EventArgs e)
{
// ... preceeding Page Load code
if (IsPostBack)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "?", "setTotals()", true);
}
}

Resources