Background Info:
For various reasons I'm having to dynamically create a RadioButtonList in a column of my GridView.
The grid presents the user with a bunch of data on which they have to leave a comment and make a decision on one of 3 radio options:
Naturally, there are a number of rows on the grid. And the way this is to work is the user makes comments and decisions on all the items before saving to the database.
This screen is to be used multiple times, so the radio buttons have to reflect the value that's stored in the database.
The Problem:
Everything works apart from one thing: the radio buttons are always being reset to their initial state (value = 1) because the grid and the controls are being re-created on postback.
Code:
Here's the working code, some of it redacted/edited...
protected void TheGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
[...]
foreach (DataControlFieldCell dc in e.Row.Cells)
{
switch (dc.ContainingField.ToString())
{
[...]
case (_ColReview):
int status = int.Parse(dc.Text);
if (status == 0)
{
dc.Text = "Not sent for review";
}
else
{
var comment = new TextBox();
comment.ID = "ReviewCommentTextBox";
comment.CssClass = "form-control";
comment.Width = 290;
dc.Controls.Add(comment);
var radioButtons = new RadioButtonList();
var rb = new ListItem();
if (status == 2) rb.Selected = true;
rb.Value = "2";
rb.Text = "Yes, Add to Watch List";
radioButtons.Items.Add(rb);
rb = new ListItem();
if (status == 3) rb.Selected = true;
rb.Value = "3";
rb.Text = "No, do not add to Watch List";
radioButtons.Items.Add(rb);
rb = new ListItem();
//initial value in database is 1, hence this will be initially selected
if (status == 1) rb.Selected = true;
rb.Value = "1";
rb.Text = "Skip: no decision";
radioButtons.ID = "RowRadioButtonList";
radioButtons.Items.Add(rb);
dc.Controls.Add(radioButtons);
}
break;
}
}
}
}
protected void BulkupdateLinkButton_Click(object sender, EventArgs e)
{
foreach(GridViewRow gvr in TheGridView.Rows)
{
[...]
int radioItemValue = 0;
foreach (DataControlFieldCell dc in gvr.Cells)
{
string cellName = dc.ContainingField.ToString();
string cellText = dc.Text;
switch(cellName)
{
[...]
case (_ColReview):
TextBox tb = (TextBox)gvr.FindControl("ReviewCommentTextBox");
comment = tb.Text;
RadioButtonList rbl = (RadioButtonList)gvr.FindControl("RowRadioButtonList");
foreach(ListItem li in rbl.Items)
{
//Issue arrives here: selected item is reset on postback, value is always 1
if (li.Selected)
{
radioItemValue = ToolBox.ConvertToInt(li.Value);
}
}
break;
}
}
if (!string.IsNullOrEmpty(comment) && (radioItemValue > 0))
{
if (radioItemValue != 1) // 1 = pending/skip
{
//code to add update the record and save the comment
[...]
}
}
}
}
Idea on solution
Now I can get around this by using a HiddenField in each row and setting up some JavaScript/JQuery to record the chosen RadioButton but I can't help but think I'm missing a trick here? Can anyone offer up a better/neater solution?
To restore a RadioButtonList to the saved selected value I believe you need to set the RadioButtonList.SelectedIndex property of the list, not the Selected property of the ListItem
Related
I need some help getting my code to work. DataGridView is proving much more complex that I had anticipated. I need someone to please show me how to fix my code, so that both the DataGridView control can be updated and my DataGridViewComboBoxColumn dropdown and DataGridViewCheckBoxColumn controls all work. I'm okay with any strategy, provided the solution you offer is somewhat elegant and complete. I've already spent far too much time trying to figure this out on my own. Any thoughts or suggestions would be greatly appreciated.
Here is a simplifcation of what my backend looks like:
MySqlDataAdapter dataAdapter = new MySqlDataAdapter(sqlRequestString, this.dbConnection);
MySqlCommandBuilder commandBuilder = new MySqlCommandBuilder(dataAdapter);
DataTable table = new DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
dataAdapter.Fill(table);
bindingSource.DataSource = table;
If I get rid of the BindingSource, how do I connect the DataTable directly to the DataGridView, so that the ComboBox and Checkbox columns are properly populated?
UPDATE
This should be a complete overview of how I am attempting to initialize my DataGridView:
private void InitializeComponent()
{
/* ... */
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.DataGridViewColumn_Section,
this.DataGridViewColumn_Indent,
this.DataGridViewColumn_Content,
this.DataGridViewColumn_Summary,
this.DataGridViewColumn_Role,
this.DataGridViewColumn_Author,
this.DataGridViewColumn_Updated});
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.DataSourceChanged += new System.EventHandler(this.dataGridView1_DataSourceChanged);
this.dataGridView1.CellEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellEnter);
this.dataGridView1.CellLeave += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellLeave);
this.dataGridView1.ColumnAdded += new System.Windows.Forms.DataGridViewColumnEventHandler(this.dataGridView1_ColumnAdded);
this.dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged);
this.dataGridView1.Leave += new System.EventHandler(this.dataGridView1_Leave);
//
// DataGridViewColumn_Section
//
this.DataGridViewColumn_Section.HeaderText = "Section";
this.DataGridViewColumn_Section.Name = "DataGridViewColumn_Section";
//
// DataGridViewColumn_Indent
//
this.DataGridViewColumn_Indent.HeaderText = "Indent";
this.DataGridViewColumn_Indent.Name = "DataGridViewColumn_Indent";
//
// DataGridViewColumn_Content
//
this.DataGridViewColumn_Content.HeaderText = "Content";
this.DataGridViewColumn_Content.MinimumWidth = 100;
this.DataGridViewColumn_Content.Name = "DataGridViewColumn_Content";
//
// DataGridViewColumn_Summary
//
this.DataGridViewColumn_Summary.HeaderText = "Summary";
this.DataGridViewColumn_Summary.Name = "DataGridViewColumn_Summary";
//
// DataGridViewColumn_Role
//
this.DataGridViewColumn_Role.HeaderText = "Minimum Signoff";
this.DataGridViewColumn_Role.Name = "DataGridViewColumn_Role";
//
// DataGridViewColumn_Author
//
this.DataGridViewColumn_Author.HeaderText = "Author";
this.DataGridViewColumn_Author.Name = "DataGridViewColumn_Author";
this.DataGridViewColumn_Author.ReadOnly = true;
//
// DataGridViewColumn_Updated
//
this.DataGridViewColumn_Updated.HeaderText = "Updated";
this.DataGridViewColumn_Updated.Name = "DataGridViewColumn_Updated";
this.DataGridViewColumn_Updated.ReadOnly = true;
/* ... */
}
public MyWinform()
{
InitializeComponent();
// Initialize DataGridView DataTable
this.dgvDataTable = new DataTable();
// Initialize DataGridView column indexes
this.idxSection = dataGridView1.Columns["DataGridViewColumn_Section"].Index;
this.idxIndent = dataGridView1.Columns["DataGridViewColumn_Indent"].Index;
this.idxContent = dataGridView1.Columns["DataGridViewColumn_Content"].Index;
this.idxSummary = dataGridView1.Columns["DataGridViewColumn_Summary"].Index;
this.idxRole = dataGridView1.Columns["DataGridViewColumn_Role"].Index;
this.idxAuthor = dataGridView1.Columns["DataGridViewColumn_Author"].Index;
this.idxLastUpdate = dataGridView1.Columns["DataGridViewColumn_Updated"].Index;
}
private void MyWinform_Load(object sender, EventArgs e)
{
DataGridView dgv = this.dataGridView1;
DataGridViewComboBoxColumn comboCol;
// Load System Menu
SystemMenu.Load(this.Handle);
// Insert selection prompt
ProcTemplateRecord selectProcPrompt = new ProcTemplateRecord();
selectProcPrompt.PrimaryKey = 0;
selectProcPrompt.ProcName = "Select from the list...";
this.procList.Insert(0, selectProcPrompt);
// Add new procedure prompt
ProcTemplateRecord newProcPrompt = new ProcTemplateRecord();
newProcPrompt.PrimaryKey = -1;
newProcPrompt.ProcName = "Start a new Safe Job Procedure";
this.procList.Add(newProcPrompt);
// Finish initializing the ComboBox dropdown list
this.comboBox1.DataSource = this.procList;
this.comboBox1.DisplayMember = "ProcName";
this.comboBox1.ValueMember = "PrimaryKey";
// Finish initializing DataGridView and bind to BindingSource
this.dataGridView1.AutoGenerateColumns = false;
/*
// Finish initializing the DataGridView ComboBox columns...
comboCol = (DataGridViewComboBoxColumn)dgv.Columns[this.idxSection];
comboCol.DataSource = Enum.GetValues(typeof(SectionType));
comboCol.ValueType = typeof(SectionType);
comboCol.DropDownWidth = ComboBoxMaxLabelWidth(comboCol);
comboCol = (DataGridViewComboBoxColumn)dgv.Columns[this.idxRole];
comboCol.DataSource = Enum.GetValues(typeof(RoleType));
comboCol.ValueType = typeof(RoleType);
comboCol.DropDownWidth = ComboBoxMaxLabelWidth(comboCol);
this.dataGridView1.DataSource = this.dgvDataTable;
*/
this.RefreshDataGridViewColumnWidths();
// Setup post-initialization DataGridViewEvent handlers
this.dataGridView1.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellValueChanged);
this.dataGridView1.CurrentCellDirtyStateChanged += new System.EventHandler(this.dataGridView1_CurrentCellDirtyStateChanged);
}
private void dataGridView1_DataSourceChanged(object sender, EventArgs e)
{
this.RefreshDataGridViewColumnWidths();
}
private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
this.RefreshButtons();
if (e.ColumnIndex == this.idxSection)
{
this.label_dgvToolTip.Visible = false;
}
else if (e.ColumnIndex == this.idxIndent)
{
this.label_dgvToolTip.Visible = false;
}
else if (e.ColumnIndex == this.idxContent)
{
this.label_dgvToolTip.Visible = false;
}
else if (e.ColumnIndex == this.idxSummary)
{
this.label_dgvToolTip.Visible = false;
}
else if (e.ColumnIndex == this.idxRole)
{
this.label_dgvToolTip.Visible = false;
}
else if (e.ColumnIndex == this.idxAuthor)
{
this.label_dgvToolTip.Visible = false;
this.label_dgvToolTip.Text = "Author column values are read only.";
this.label_dgvToolTip.Visible = true;
}
else if (e.ColumnIndex == this.idxLastUpdate)
{
this.label_dgvToolTip.Visible = false;
this.label_dgvToolTip.Text = "Updated column values are read only.";
this.label_dgvToolTip.Visible = true;
}
else
{
this.label_dgvToolTip.Visible = false;
}
this.idxActiveColumn = e.ColumnIndex;
this.idxActiveRow = e.RowIndex;
}
private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
{
this.label_dgvToolTip.Visible = false;
this.RefreshButtons();
}
private void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
DataGridView dgv = this.dataGridView1;
if ((e.Column.DataPropertyName == "PageSection") &&
(e.Column.CellType != typeof(DataGridViewComboBoxCell)))
{
var cbo = GetComboBoxColumn(e.Column);
cbo.DataSource = Enum.GetValues(typeof(SectionType));
cbo.ValueType = typeof(SectionType);
dgv.Columns.Remove(e.Column);
dgv.Columns.Add(cbo);
}
else if ((e.Column.DataPropertyName == "UserRole") &&
(e.Column.CellType != typeof(DataGridViewComboBoxCell)))
{
var cbo = GetComboBoxColumn(e.Column);
cbo.DataSource = Enum.GetValues(typeof(RoleType));
cbo.ValueType = typeof(RoleType);
dgv.Columns.Remove(e.Column);
dgv.Columns.Add(cbo);
}
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
this.RefreshButtons();
}
private void dataGridView1_Leave(object sender, EventArgs e)
{
DataGridView dgv = this.dataGridView1;
if (dgv.SelectedCells.Count == 0)
{
this.idxActiveColumn = -1;
this.idxActiveRow = -1;
}
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
DataGridViewComboBoxCell sectionCell = (DataGridViewComboBoxCell)dgv.Rows[e.RowIndex].Cells[this.idxSection];
DataGridViewTextBoxCell indentCell = (DataGridViewTextBoxCell)dgv.Rows[e.RowIndex].Cells[this.idxIndent];
DataGridViewComboBoxCell roleCell = (DataGridViewComboBoxCell)dgv.Rows[e.RowIndex].Cells[this.idxRole];
Int32 colIndex = e.ColumnIndex;
try
{
if (colIndex == this.idxIndent)
{
int number;
string cellValue = indentCell.Value.ToString();
bool isNumeric = int.TryParse(cellValue, out number);
if (!isNumeric)
{
cellValue = cellValue.Substring(0, cellValue.Length - 1);
indentCell.Value = cellValue;
}
}
// Column resizing code goes last
this.RefreshDataGridViewColumnWidths();
this.dgvIsDirty = true;
}
catch (Exception ex)
{
throw new Exception("Failed to refresh DataGridView on cell change.", ex);
}
}
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
DataGridView dgv = (DataGridView)sender;
try
{
if (dgv.IsCurrentCellDirty)
{
// This fires the cell value changed handler below
dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
this.RefreshDataGridViewColumnWidths();
}
}
catch (Exception ex)
{
throw new Exception("Failed to commit edit of DataGridView cell.", ex);
}
}
This is the code I am using to update my DataGridView contorl:
// Load the data from the database into the DataGridView
this.dbif.GetProcedure(this.procList.ElementAt(selectedIndex).PrimaryKey, ref this.dgvDataTable);
DataRow[] rows = this.dgvDataTable.Select();
//Object dgvDataSource = dgv.DataSource;
//dgv.DataSource = null;
foreach (DataRow dataRow in rows)
{
DataGridViewRow dgvRow = new DataGridViewRow();
dgvRow.CreateCells(dgv);
dgvRow.Cells[idxSection].Value = dataRow.Field<string>(0);
dgvRow.Cells[idxIndent].Value = dataRow.Field<byte>(1);
dgvRow.Cells[idxContent].Value = dataRow.Field<string>(3);
dgvRow.Cells[idxSummary].Value = dataRow.Field<UInt32>(4) != 0;
dgvRow.Cells[idxRole].Value = dataRow.Field<string>(5);
dgvRow.Cells[idxAuthor].Value = dataRow.Field<string>(6) + dataRow.Field<string>(7);
dgvRow.Cells[idxLastUpdate].Value = dataRow.Field<DateTime>(8).ToString();
dgv.Rows.Add(dgvRow);
}
//dgv.DataSource = dgvDataSource;
This is how my enumerations are defined:
public enum SectionType
{
ESJP_SECTION_HEADER = 1, // start with 1 for database compatibility
ESJP_SECTION_FOOTER,
ESJP_SECTION_BODY
}
public enum RoleType
{
ESJP_ROLE_NONE = 1, // start with 1 for database compatibility
ESJP_ROLE_TEST_ENG,
ESJP_ROLE_FEATURE_LEAD,
ESJP_ROLE_TEAM_LEAD
}
There are a number of issues/improvements. There are too many unknowns about the data to fix everything, but some techniques shown here may help.
1. Manually populating the DGV
You ought not have to do that. Just setting the DataTable as the DataSource will work most of the columns.
2. Expressions
You have 2 expressions where you populate the dgv:
dgvRow.Cells[idxSummary].Value = dataRow.Field<UInt32>(4) != 0;
dgvRow.Cells[idxAuthor].Value = dataRow.Field<string>(6) + dataRow.Field<string>(7);
This leads me to believe the dgv is ReadOnly. Otherwise you will have trouble with those. The Summary for instance: if the user Unchecks the column, you can set that value to 0, but what if they check it? How will you know what value to set??
Indent as Byte seems odd too - almost like it is a boolean.
3. Combos
In a previous question, the dgv was populated from a List<Class>. With that as the `DataSource, an Enum works well because the 2 properties were of that Type. With an enum, the following works:
cbo.ValueType = typeof(RoleType);
It's less likely to work with a DataTable as in version 1, 2 or 3 of this question because there is no db/Datatable type of SectionType or RoleType. In other cases where there is a translation - show the user "ESJP_SECTION_HEADER" but store 2 in the DataTable and ultimately the DB - a small NameValue pairs list will work. A different data model means a different approach to the DGV cbo.
It now looks like those are text columns (I've asked 3 times). If so, you really just need to constrain the selection to the enum names. In the IDE, paste in the text for the Items property:
Alternatively, you can do so in code:
private string[] secList = {"ESJP_SECTION_HEADER","ESJP_SECTION_FOOTER",
"ESJP_SECTION_BODY"};
...
((DataGridViewComboBoxColumn)dgv1.Columns["PageSection"]).Items.AddRange(secList);
AutoGenerateColumns
When the DataSource for a DGV is set, by default it will automatically create a DGVcolumn for each DTColumn, and this works well for the most part. Sometimes you'll want some small tweak like hide an Id column, or change a TextColumn to a CBOColumn. Code in the ColumnAddedEvent to make these changes rather than manually laying out columns can work well.
But since there are quite a few such such changes and since you have already layed out columns in the IDE, you want to be sure to set AutoGenerateColumns to false somewhere in code. Otherwise it will add still more columns.
Setup
Things you may or may not have done in the DGV designer:
Add the columns in whatever order you wish, but be sure to assign the DataPropertyName to the name used in the SQL query. Leave it blank for Author.
Expression columns like Author means either changing the query or doing some formatting in the DGV. For this, add First and Last name columns to the DGV as well as the Author column. Make the first two invisible. The code below shows the formatting. (Make sure that the compound column (Author) appears after the parts!).
Normally, I would try to do that in SQL: SELECT (First + Last) AS Author, but if you do not want to mess with that query, you can concat in DGV events.
Be sure to add the names for the Page and Role columns to the Items collection.
Then, the rest is fairly simple:
private DataTable dtF;
...
string SQL = "SELECT PageSection, Indent, Content, SummaryId, "
+ "UserRole, AuthorFirstN, AuthorLastN, LastUpdated FROM FellPage";
using (var dbCon = new MySqlConnection(MySQLConnStr))
using (var cmd = new MySqlCommand(SQL, dbCon))
{
dbCon.Open();
dtF = new DataTable();
dtF.Load(cmd.ExecuteReader());
}
// IMPORTANT!!!
dgv1.AutoGenerateColumns = false;
dgv1.DataSource = dtF;
The formatting event:
private void dgv1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (dgv1.Rows[e.RowIndex].IsNewRow)
return;
if (e.ColumnIndex == 7) // ie "Author"
{
e.Value = dgv1.Rows[e.RowIndex].Cells[6].Value.ToString() + ", " +
dgv1.Rows[e.RowIndex].Cells[5].Value.ToString();
e.FormattingApplied = true;
}
}
Result:
It is very important to turn off AutoGenerateColumns. By default, the dgv will add columns for everything in the source. Since you added them, set that to false in the code (there is no IDE property for it).
By virtue of Summary and Indent being defined as check columns, it translates non zero as true. I have no idea how you will edit any SummaryId value. That should probably be a text column so they can enter a value, if that is allowed (that col could be read only too?).
My query and such arent as complex as yours, and surely there are some details I/we are unaware of which have been omitted. But there is certainly a much less gyrations and code to get it working...whatever this is.
Being bound to a DataTable, when the user edits anything, the changes flow thru to the underlying DataTable (use the various Validating events to check their work). The DataTable in turn tracks the state of each row - new, changed, deleted - so later you can:
var changes = dtF.GetChanges();
This will return all the rows which have been changed since the last AcceptChanges().
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 a dynamically created button with an onclick event handler. The problem is that when I click the button it does not hit the event in the code-behind.
protected void gvOrder_RowDataBound(object sender, GridViewRowEventArgs e)
{
DataTable dt = ds.Tables[0];
DropDownList ddl = new DropDownList();
TextBox txt = new TextBox();
int index = 1;
if (e.Row.RowType == DataControlRowType.DataRow)
{
ddl = e.Row.FindControl("ddlNewO") as DropDownList;
txt = e.Row.FindControl("txtNewT") as TextBox;
}
foreach (DataRow r in dt.Rows)
{
string listitem = Convert.ToString(index);
ddl.Items.Add(listitem);
index++;
}
ddl.SelectedIndex = e.Row.RowIndex;
if (e.Row.RowIndex == 0)
{
ddl.Enabled = false;
txt.Enabled = false;
}
else if (e.Row.RowIndex != 0)
{
ddl.Items.Remove("1");
//Create ED button
if (e.Row.RowType == DataControlRowType.DataRow)
{
Button btnED = new Button();
btnED.ID = "btnED";
btnED.CssClass = "buttonsmall";
//btnED.CommandName = "ED";
btnED.EnableViewState = true;
btnED.Click += new EventHandler(btnED_Click);
foreach (DataRow r in dt.Rows)
{
btnED.Attributes.Add("ID", r.ItemArray[2].ToString());
if (r.ItemArray[3].ToString() == "1")
{
btnED.Text = "Disable";
}
else
{
btnED.Text = "Enable";
}
//Add button to grid
e.Row.Cells[5].Controls.Add(btnED);
}
}
}
}
protected void btnED_Click(object sender, EventArgs e)
{
// Coding to click event
}
So the problem here is that when the page is being recreated on post back - there is no more button! Dynamic controls need to be added on the page on every post back to fire events properly. In your case however on the first load when the GridView is binding you add the button to the page. But on the post back after the click the button is not added again, because GridView is not data bound again. Therefore ASP.NET cannot derive the source of the event, and supresses it.
Fix here is to bind GridView with data on every post back. Literally if you had if (!IsPostBack) - remove it. Or you can add the button in the template field and play with visibility - may be an approach as well.
You need to add a click handler on Row Created not on Data Bound I believe.
protected void gvOrderRowCreated(object sender, GridViewRowEventArgs e)
{
switch (e.Row.RowType) {
case DataControlRowType.DataRow:
Button btn = (Button)e.Row.FindControl("btnED");
btn.Command += btnED_Click;
break;
}
}
Here is my code which populates the question from db table based on their object type (droprdown,checkbox,radioutton..)
if (str.Trim().ToLower() == "dropdown box")
{
string[] strArr = strOptions.Split('|');
DropDownList ddl = new DropDownList();
ddl.ID = "ddl";
ddl.CssClass = "CheckBox";
ddl.Width = Unit.Pixel(100);
// ddl.Items.Add(new ListItem("test", "test"));
if (strArr.Count() > 0)
{
foreach (string s in strArr)
{
ddl.Items.Add(new ListItem(s, s));
}
}
else
{
ddl = new DropDownList();
ddl.ID = "ddlContent1";
ddl.Width = Unit.Pixel(150);
plc.Controls.Add(ddl);
}
plc.Controls.Add(ddl);
}
if (str.Trim().ToLower() == "checkbox list")
{
string[] strArr = strOptions.Split('|');
if (strArr.Count() > 0)
{
foreach (string s in strArr)
{
CheckBox chk = new CheckBox();
chk.ID = s;
chk.Text = s;
chk.CssClass = "CheckBox";
if (strFooterOptions == "If all of the above are checked, please SUBMIT. [Click here to Submit]")
chk.Attributes.Add("onclick", "checkAllCheckBox()");
plc.Controls.Add(chk);
plc.Controls.Add(new LiteralControl("<br />"));
}
}
and my prev and next button , when you hit next it shows you another questions in another sections.
protected void btnNext_Click(object sender, EventArgs e)
{
// int section = 1;
section = section + 1;
btnPrev.Enabled = true;
FillSection();
}
protected void btnPrev_Click(object sender, EventArgs e)
{
section = section - 1;
FillSection();
}
How can i create a method to insert responses to database when i hit next?.
Any idea Appreciate
Thanks
It depends on how you store your survey options I think. I made a similiar thing, storing all options in same row in database. First created a cookie to store what survey is taken (ex: all city pages have surveys and London is taken). Then I created a function to do the db stuff,
IF NOT EXISTS (Select * from your_survey_table where column=cookievalue)
INSERT INTO your_survey_table (your_columns_here) VALUES (#your_values)
ELSE
UPDATE your_survey_table SET option2=#your_value
I have a DropDownlist in the GridView, which should be visible only when edit is clicked. I have bound the DropDownList from code behind. When I click on Edit, the label value of that cell should automatically get selected in the DropDownList.
The code I have tried is:
protected void GridView3_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
SqlCommand cmd = new SqlCommand("SELECT Location_Name FROM Location_Table");
DropDownList bind_drop = (e.Row.FindControl("DropList") as DropDownList);
bind_drop.DataSource = this.ExecuteQuery(cmd, "SELECT");
bind_drop.DataTextField = "Location_Name";
bind_drop.DataValueField = "Location_Name";
bind_drop.DataBind();
string Loc_type = (e.Row.FindControl("id2") as Label).Text.Trim();
bind_drop.Items.FindByValue(Loc_type).Selected = true;
}
}
When I run the code, it gives an exception error Object reference not set in the last line of the above code.
Cannot find out whats wrong. Kindly help
You must ensure that your list contains label value.
var index = DropDownList1.Items.IndexOf(Loc_type );
if(index > 0)
{
DropDownList1.SelectedIndex = index;
}
else
{
Console.WriteLine("item does not exist");
}