I'm adding dropdownlists to my page depending on a amount of database entries and when I press the button I want to get the selected values in each dropdownlist.
I tried this
foreach(DropDownList a in Form.Controls.OfType<DropDownList>())
{
Response.Write(a.SelectedValue);
}
but it doesn't find any dropdownlist on the page. Below is the code I use to add the dorpdownlists.
protected void Page_Init()
{
string product = Request.QueryString["product"];
foreach (productoption r in dbcon.GetOption(product))
{
TableRow row = new TableRow();
TableCell cel1 = new TableCell();
TableCell cel2 = new TableCell();
DropDownList dropdown1 = new DropDownList();
dropdown1.CssClass = "productdropdown";
foreach (suboption f in dbcon.GetSubOption(r.ProductOptionID))
{
dropdown1.Items.Add(f.SubOptionName + " +$" +f.SubOptionPrice);
}
cel1.Text = "<b>" + r.OptionName + "</b>";
cel2.Controls.Add(dropdown1);
row.Cells.Add(cel1);
row.Cells.Add(cel2);
Table1.Rows.Add(row);
}
TableRow row2 = new TableRow();
TableCell cell3 = new TableCell();
Button cartbutton = new Button();
cartbutton.ID = product;
cartbutton.CssClass = "btn_addcart";
cartbutton.Click += cartbutton_OnClick;
cartbutton.Text = "Add to cart";
cell3.Controls.Add(cartbutton);
row2.Cells.Add(cell3);
Table1.Rows.Add(row2);
}
foreach (TabelRow row in Table1.Rows)
{
if(row.Cells.Count > 0)
{
if (row.Cells[1].Controls.Count > 0 && row.Cells[1].Controls[0].GetType() == typeof(DropDownList))
{
Response.Write(a.SelectedValue);
}
}
}
First you should make a function that looks for a control type in a ControlCollection and returns a list of found controls. Something like that:
public List<T> GetControlsOfType<T>(ControlCollection controls)
{
List<T> ret = new List<T>();
try
{
foreach (Control control in controls)
{
if (control is T)
ret.Add((T)((object)control));
else if (control.Controls.Count > 0)
ret.AddRange(GetControlsOfType<T>(control.Controls));
}
}
catch (Exception ex)
{
//Log the exception
}
return ret;
}
and then you can get all DropDownList like that:
List<DropDownList> ret = GetControlsOfType<DropDownList>(this.Page.Controls);
I hope it helped.
You should be adding controls inside another control for example a panel
*Also you dont need to define controls at page init, you can do that at page load and they will retain their value*
protected void Page_Load(object sender, EventArgs e)
{
loadControls();
}
//For Instance lets take a dropdownlist and add it to a panel named testpanel
Protected void loadControls()
{
DropdownList ddlDynamic = new DropdownList();
//give this control an id
ddlDynamic.Id = "ddlDynamic1"; // this id is very important as the control can be found with same id
//add data to dropdownlist
//adding to the panel
testpanel.Controls.Add(ddlDynamic);
}
//Now we have to find this control on post back for instance a button click
protected void btnPreviousSet_Click(object sender, EventArgs e)
{
//this will find the control here
//we will you the same id used while creating control
DropdownList ddlDynamic1 = testpanel.FindControl("ddlDynamic1") as DropdownList;
//can resume your operation here
}
Related
I'm having a problem to get controls/ controls id that I have created manually from code behind. after doing research I found if I create the table and its all component including any controls in Page_Init() method, when rendering after postback the text value of textbox control should be available to the page. i tried to locate the textbox control using FindControl() method. when debugging it only reach to the line where I tried to locate the control using FindControl() and then throw an exception "Object reference not set to an instance of an object" bellow is the Page_Init() method
protected void Page_Init(object sender, EventArgs e)
{
Table tb = new Table();
tb.ID = "Table1";
TableRow row1 = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TableCell cell3 = new TableCell();
TextBox txtbx = new TextBox();
Button btn = new Button();
cell1.Text = "Name: ";
txtbx.ID = "table1_text_input";
txtbx.ValidationGroup = "rosy";
cell2.Controls.Add(txtbx);
btn.Text = "Get the input";
btn.ValidationGroup = "rosy";
btn.Click += getBoxinput_Click;
cell3.Controls.Add(btn);
// adding cells to row1
row1.Cells.Add(cell1);
row1.Cells.Add(cell2);
row1.Cells.Add(cell3);
// adding row to table1
tb.Rows.Add(row1);
Panel1.Controls.Add(tb);
}
below is the button click event that supposes to display the control id and its text. I'm stuck with this for the last couple of days. any help will be appreciated.
protected void getBoxinput_Click(object sender, EventArgs e)
{
try
{
if (IsPostBack)
{
Table t = (Table)Page.FindControl("Panel1").FindControl("Table1");
TextBox tbox;
foreach (TableRow tr in t.Rows)
{
foreach (TableCell tc in tr.Cells)
{
foreach (Control cnt in tc.Controls)
{
if (cnt.GetType() == typeof(TextBox))
{
tbox = (TextBox)cnt;
display.Text += "control id: " + tbox.ID + " control input: " + tbox.Text + "<br/>";
}
}
}
}
}
}
catch (NullReferenceException ex)
{
display.Text += ex.Message;
}
}
Maybe I am missing something but why don't you just put all the controls in the global scope of the class (instead of just creating the instances inside Page_Init) so that you can access them in any part of your class. Of course I am assuming that Page_Init and getBoxinput_Click are in the same class.
EDIT:
Here is the example on how to put the variables in the global scope:
Table tb; //Declare variables outside any function.
protected void getBoxinput_Click(object sender, EventArgs e)
{
tb = new Table(); //Initialize them inside a function.
}
This way you will be able to access tb inside any function.
Your code is working perfectly. Here is what I used for the form markup:
<form id="form1" runat="server">
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
<asp:Label ID="display" runat="server"></asp:Label>
</form>
I have this situation:
... a normal RadGrid with data. And, if I clic on a row, I want to obtain this:
... a list of label-textbox pair (please pay attention: these list of data are obtained from the row, but are not part of it).
With the first RadGrid it's all okay.
Therefore, I have used a simple HTML Table for the list of pair (in the second image). This list being generated code-behind, from database.
The problem is the update of the TextBoxs: if I edit these textboxes and do clic on the Update Botton, starts the myRadGrid_UpdateCommand method. But I can't find a way to manage these textboxes (they don't appear in myRadGrid.Controls or else).
So I have tried to use another RadGrid inside the first RadGrid, but with no luck... Maybe I have to use another different Telerik control?
Someone know how I can do this?
This is part of my implementation:
protected void myRadGrid_NeedDataSource(object source, GridNeedDataSourceEventArgs e)
{
this.myRadGrid.DataSource = this.dtListaDettagli;
this.dtListaDettagli.PrimaryKey = new DataColumn[] { this.dtListaDettagli.Columns["key"] };
}
protected void myRadGrid_ItemCreated(object sender, Telerik.Web.UI.GridItemEventArgs e)
{
if (e.Item is GridEditFormItem && e.Item.IsInEditMode)
{
GridEditFormItem item = (GridEditFormItem)e.Item;
UserControl userControl = (UserControl)e.Item.FindControl(GridEditFormItem.EditFormUserControlID);
var listOfDetails = this.Session["listOfDetails"];
//...
var dtoTrav = (List<Detail_Type_N>) listOfDetails;
PopolaUC(dtoTrav, userControl, e.Item.ItemIndex);
}
}
private void PopolaUC<T>(List<T> data, UserControl uc, int index) where T : FlussiBaseDto
{
// ...
RadPane radPane = uc.FindControl("RadPane1") as RadPane;
var properties = TypeDescriptor.GetProperties(typeof(Detail_Type_N));
// ...
var dettaglioSelected = (from x in data
where x.IdFlusso == idFlussoSelected && x.ProgDettaglio == progDettaglioSelected
select x).FirstOrDefault();
HtmlTable htmlTable = new HtmlTable();
htmlTable.ID = "DettaglioSinistro";
var tRow = new HtmlTableRow();
int i = 0;
foreach (PropertyDescriptor prop in properties)
{
i++;
if (i > 3) // organizza la sottotabella in 2 colonne
{
tRow = new HtmlTableRow();
i = 1;
}
// Set label:
HtmlTableCell tLabel = new HtmlTableCell();
var stringInNormalCase = Regex.Replace(prop.Name, "(\\B[A-Z])", " $1");
tLabel.InnerText = stringInNormalCase;
tRow.Cells.Add(tLabel);
// Set TextBox:
HtmlTableCell tCell = new HtmlTableCell();
// ...
TextBox box = new TextBox();
box.Text = Convert.ToString(prop.GetValue(detailSelected));
box.ID = string.Format("my_{0}", prop.Name);
tCell.Controls.Add(box);
tRow.Cells.Add(tCell);
htmlTable.Rows.Add(tRow);
}
radPane.Controls.Add(htmlTable);
}
protected void myRadGrid_UpdateCommand(object source, GridCommandEventArgs e)
{
GridEditableItem editedItem = e.Item as GridEditableItem;
UserControl userControl = (UserControl)e.Item.FindControl(GridEditFormItem.EditFormUserControlID);
//Prepare new row to add it in the DataSource
DataRow[] changedRows = this.dtListaDettagli.Select("key = " + editedItem.OwnerTableView.DataKeyValues[editedItem.ItemIndex]["key"]);
// ... and then?
catch (Exception ex)
{
changedRows[0].CancelEdit();
Label lblError = new Label();
lblError.Text = string.Format("Errore nell'aggiornamento movimento. Errore: {0} ", ex.Message);
lblError.ForeColor = System.Drawing.Color.Red;
RadGridIpa.Controls.Add(lblError);
e.Canceled = true;
}
}
You cannot generate TextBoxes and Labels dynamically.
Instead, you want to use Edit Form.
For example,
<telerik:RadGrid ID="RadGrid1" ...>
<MasterTableView>
...
<EditFormSettings>
Place those textboxes and lables here.
</EditFormSettings>
</MasterTableView>
</telerik:RadGrid>
I have an existing drop down list(namely ddlA). On selecting a value in which, I am getting a cascading drop down list(ddlB). The requirement is, I need to create a button on the webform. By clicking the button, I would need to create drop down list dynamically of type ddlA. But here is the tricky part, I am required to present all the values in this dropdown except the selected value in the previous selection(s) of type ddlA.
Here is my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<DropDownList> DDLList = new List<DropDownList>();
Session["DDLs"] = DDLList;
}
else
{
List<DropDownList> existingDropDowns = (List<DropDownList>)Session["DDLs"];
//Add all existing DropDownLists to Panel
foreach (DropDownList dropdown in existingDropDowns)
{
Panel1.Controls.Add(dropdown);
dropdown.AutoPostBack = true;
Panel1.Controls.Add(new LiteralControl("<br/>"));
}
Session["DDLs"] = existingDropDowns;
}
}
and here is my button click event code:
protected void ddlAdditionBtn_Click(object sender, EventArgs e)
{
List<DropDownList> existingDropDowns = (List<DropDownList>)Session["DDLs"];
DropDownList newDropDown = new DropDownList();
newDropDown.ID = "DDL" + existingDropDowns.Count.ToString();
existingDropDowns.Add(newDropDown);
Panel1.Controls.Add(newDropDown);
newDropDown.AutoPostBack = true;
Panel1.Controls.Add(new LiteralControl("<br/>"));
Session["DDLs"] = existingDropDowns;
}
Below is the code to connect the existing dropdown list with the database.
protected void GetDropDowndata()
{
DataTable ddlData= lookupCache.AccessLookupData(Constants.GroupSelectionFilter.ToString());
if (ddlData != null && ddlData.Rows.Count > 0)
{
ddlData.DefaultView.Sort = "DropDownValue";
ddlData = groupsData.DefaultView.ToTable();
ddlSelectGrp.DataSource = ddlData;
ddlSelectGrp.DataTextField = "DropDownValue";//ddlSelectGrp is the existing dropdown id
ddlSelectGrp.DataValueField = "DropDownBoxID";
ddlSelectGrp.DataMember = "DropDownGroup";
ddlSelectGrp.DataBind();
ddlSelectGrp.Items.Insert(1, Constants.GroupAll.ToString());
ddlSelectGrp.SelectedIndex = 1;
btnGroupSave.Enabled = true;
btnGroupSave.CssClass = "saveButton";
}
}
But I have no idea on how to connect the dynamically generated dropdownlist with the datasource and that too without the selected value(s) in the previous dropdown list(s).
Ok The problem is I have a grid that I need to have paging on it with pages shown as numbers
I want to add two link button to the paging section to alow user to navigate to next page prev page
Here is my code
protected void CustomerGridView_RowCreated(object sender, GridViewRowEventArgs e)
{
var grid = sender as GridView
if (e.Row.RowType == DataControlRowType.Pager)
{
var prvLink = new LinkButton();
prvLink.Text = "<";
prvLink.CommandName = "Page";
prvLink.CommandArgument = "Prev";
prvLink.EnableViewState = true;
var nextLink = new LinkButton();
nextLink.Text = ">";
nextLink.CommandName = "Page";
nextLink.CommandArgument = "Next";
nextLink.EnableViewState = true;
var prvCell = new TableCell();
var nextCell = new TableCell();
prvCell.Controls.Add(prvLink);
nextCell.Controls.Add(nextLink);
Table pagerTable = e.Row.Controls[0].Controls[0] as Table;
TableRow row = pagerTable.Rows[0];
row.Cells.AddAt(0, prvCell);
row.Cells.AddAt(row.Cells.Count, nextCell);
if (grid.PageIndex == 0)
{
prvCell.Enabled = false;
}
if (grid.PageIndex == grid.PageCount - 1)
{
nextCell.Enabled = false;
}
}
}
its perfectly working and users are able to navigate back and forward (and I can see grid RowCommand event getting fired)
The problem is I do not want to put the code inside my page (to make my page tiny and put the responsibility to an other class )
here is my class
public class GridStyler
{
private GridView _grid;
public GridStyler(GridView grid)
{
_grid = grid;
}
public void AddNextPreviousOnPager()
{
_grid.RowCreated += _grid_RowCreated;
}
void _grid_RowCreated(object sender, GridViewRowEventArgs e)
{
var grid = sender as GridView;
if (e.Row.RowType == DataControlRowType.Pager)
{
var prvLink = new LinkButton();
prvLink.Text = "<";
prvLink.CommandName = "Page";
prvLink.CommandArgument = "Prev";
prvLink.EnableViewState = true;
var nextLink = new LinkButton();
nextLink.Text = ">";
nextLink.CommandName = "Page";
nextLink.CommandArgument = "Next";
nextLink.EnableViewState = true;
var prvCell = new TableCell();
var nextCell = new TableCell();
prvCell.Controls.Add(prvLink);
nextCell.Controls.Add(nextLink);
Table pagerTable = e.Row.Controls[0].Controls[0] as Table;
TableRow row = pagerTable.Rows[0];
row.Cells.AddAt(0, prvCell);
row.Cells.AddAt(row.Cells.Count, nextCell);
if (grid.PageIndex == 0)
{
prvCell.Enabled = false;
}
if (grid.PageIndex == grid.PageCount - 1)
{
nextCell.Enabled = false;
}
}
}
}
then I should be able to call a code like that in my page load and it should create the link buttons and response to click of them
var g = new GridStyler(CustomerGridView);
g.AddNextPreviousOnPager();
what happens is the link buttons are created just fine but when user clicks them page get refreshed but RowCommand never get fired (they get fired of course when user clicks other buttons but not this two dynamically created buttons)
Any suggestion is really appreciated
I'm creating textboxes in the Page_Load event and giving them values, however whenever I load the details I am getting the same output. I always seem to get the first output I got, even on subsequent searches.
Here's what my code with the irrelevant information missing:
Textbox txtName = New Textbox();
protected void Page_Load(object sender, EventArgs e)
{
LoadData();
}
void LoadData()
{
txtName.Text = DropDownList.SelectedValue;
tableCell.Controls.Add(txtName);
}
If DropDownList has two values (e.g. "Item 1" and "Item 2") and has autopostback enabled, first time it will generate and show "Item 1" in the textbox (the default value for the DropDownList), but if this is changed and the autopostback fires, the textbox does not change.
I've tried getting around this by creating a new TextBox, overriding the "LoadPostData" function to prevent this from loading, which got around the issue there, but then I couldn't view the data afterwards.
Any idea how I could get around this? I may be approaching this in the wrong way.
Edit: I've added another item to DropDownList that removes TextBox, so that it can be re-created again. It seems to show the correct data when it is re-created after being removed, but if I'm attempting to just edit it, this isn't updating correctly.
Edit2: Here's the rest of the code for this page in case this helps at all. The objects which I'm having issues with are SBUName and SBUComments, which are both TextBoxes. The same issue is also happening for SBUClientDropdown but I believe the resolution will be similar:
DBHandler DBHandler = new DBHandler();
List<string> clients = new List<string>();
List<string> clientGroups = new List<string>();
List<string> sbus = new List<string>();
// Objects for SBU changes
string previousSBU = "";
string previousSBUClient = "";
TextBox SBUName = new TextBox() { ID = "SBUName" };
TextBox SBUComments = new TextBox() { ID = "SBUComments" };
DropDownList SBUClientDropdown = new DropDownList();
protected void Page_Load(object sender, EventArgs e)
{
clients = DBHandler.GetClients();
clientGroups = DBHandler.GetClientGroups();
if (!Page.IsPostBack)
{
foreach (string client in clients)
{
SBUClientList.Items.Add(GenerateItem(client));
ClientList.Items.Add(GenerateItem(client));
}
foreach (string clientGroup in clientGroups)
ClientGroupList.Items.Add(GenerateItem(clientGroup));
}
if ((SBUClientList.SelectedValue.ToString() != previousSBUClient) || (SBUList.SelectedValue.ToString() != previousSBU))
{
previousSBUClient = SBUClientList.SelectedValue.ToString();
previousSBU = SBUList.SelectedValue.ToString();
sbus = DBHandler.GetSBUs(SBUClientList.SelectedValue);
SBUList.Items.Clear();
foreach (string sbu in sbus)
SBUList.Items.Add(GenerateItem(sbu));
LoadSBU();
}
}
void LoadSBU()
{
if ((SBUClientList.SelectedValue.Trim().Length > 0) && (SBUList.SelectedValue.Trim().Length > 0))
{
Entity thisSBU = DBHandler.GetSBUInformation(SBUClientList.SelectedValue, SBUList.SelectedValue);
SBUTable.Rows.Add(GenerateHeaderRow("Client Name", "SBU Name", "Comments"));
SBUClientDropdown.Items.Clear();
foreach (string client in clients)
SBUClientDropdown.Items.Add(GenerateItem(client));
SBUClientDropdown.SelectedValue = SBUClientList.SelectedValue;
SBUClientDropdown.SelectedIndex = SBUClientList.SelectedIndex;
TableCell SBUClientCell = new TableCell();
SBUClientCell.Controls.Add(SBUClientDropdown);
SBUName.Text = thisSBU.sSBUName;
TableCell SBUNameCell = new TableCell();
SBUNameCell.Controls.Add(SBUName);
SBUComments.Text = thisSBU.sSBUComments;
TableCell SBUCommentsCell = new TableCell();
SBUCommentsCell.Controls.Add(SBUComments);
SBUTable.Rows.Add(GenerateRow(SBUClientCell, SBUNameCell, SBUCommentsCell));
Button SBUSaveButton = new Button();
SBUSaveButton.Click += new EventHandler(this.SBUSaveChanges);
SBUSaveButton.Text = "Save SBU Changes";
TableCell SBUButtonCell = new TableCell();
SBUButtonCell.Controls.Add(SBUSaveButton);
SBUButtonCell.ColumnSpan = 3;
TableRow SBUFooter = GenerateRow(SBUButtonCell);
SBUFooter.TableSection = TableRowSection.TableFooter;
SBUTable.Rows.Add(SBUFooter);
}
}
void ShowMessage(string message)
{
OutputString.Text = "<div class=\"message\">" + message + "</div>";
}
ListItem GenerateItem(string input)
{
ListItem output = new ListItem();
output.Text = input;
return output;
}
TableCell GenerateCell(string text)
{
TableCell output = new TableCell();
output.Text = text;
return output;
}
TableRow GenerateRow(params TableCell[] cells)
{
TableRow output = new TableRow();
foreach (TableCell cell in cells)
output.Cells.Add(cell);
return output;
}
TableRow GenerateHeaderRow(params string[] columns)
{
TableRow output = new TableRow();
output.TableSection = TableRowSection.TableHeader;
foreach (string column in columns)
{
TableCell thisCell = new TableCell();
thisCell.Text = column;
output.Cells.Add(thisCell);
}
return output;
}
previousSBUClient and previousSBU will always be blank on each post back, so why do you compare against them on the Page_Load? If you want their values saved between postbacks you need to save them in ViewState, I suggest code like:
public string PreviousSBU
{
get { return Convert.ToString(ViewState["PreviousSBU"] ?? string.Empty); }
set { ViewState["PreviousSBU"] = value; }
}
Perhaps its because you add multiple header rows to the table, and only the contents between the first through the second get displayed? Any header rows after added don't get displayed?
On each postback you add a new header row. But the TextBox's are created on each postback and not saved between, so you shouldn't be seeing anything at all if thats the case.
To render txtName to the page, you should have something like:
this.Controls.Add(txtName); somewhere on the page, preferably in the Page_Init, though for what you've listed, at least before the LoadData() call in Page_Load.
Taking a guess at the missing code but are you databinding your dropdown list? If you are you may be doing it every time instead of just when the page is not a postback. Like I say, guessing at what's not in your question but you might want consider something like this instead:
if (!Page.IsPostback)
{
MyDropDownList.DataSource = blah;
MyDropDownList.DataBind();
}
myTextBox.Text = MyDropDownList.SelectedValue;
Create your controls in OnInit event, becouse viewstate serialization happens between oninit and onload. Also check if it is postback, to avoid overwriting values from viewstate.
I remember strange things happening if you don't supply an ID to the textbox, are you doing this?
txtName.ID="txtName";`