I am wondering how I can get the value from an asp.net textbox that is dynamically created inside an asp:datalist.
I would like to then insert these values back into the database.
Let say we have the following output on the web page from the datalist. (Each Question is a asp:textbox)
Question 1
Answer 1
Answer 2
Update Button
Question 2
Answer 1
Answer 2
Update Button
Question 3
Answer 1
Answer 2
Update Button
For example: I would like to get the value from Question 2 textbox and then parse the value to my database insert method.
How can this be done as the text boxes are generated dynamically in the data list?
I have written the following:
<asp:DataList runat="server" id="dgQuestionnaire" DataKeyField="QuestionID" CssClass="confirm">
<ItemTemplate>
<h3>Question <asp:Label ID="lblOrder" runat="server" Text='<%# Container.ItemIndex + 1 %>'></asp:Label></h3>
<asp:TextBox runat="server" ID="QuestionName" Text='<%# Eval("QuestionText") %>' CssClass="form"></asp:TextBox>
<asp:DataList ID="nestedDataList" runat="server">
<ItemTemplate>
<asp:TextBox ID="AnswerBox" runat="server" CssClass="form" Text='<%# Eval("AnswerTitle") %>' Width="300px"></asp:TextBox>
</ItemTemplate>
</asp:DataList>
<asp:Button runat="server" ID="updateName" CssClass="button_update" style="border: 0px;" onClick="UpdateQuestionName_Click" />
</ItemTemplate>
</asp:DataList>
And here the code behind (sorry about the length)
protected void UpdateQuestionName_Click(object sender, EventArgs e)
{
int QuestionnaireId = (int)Session["qID"];
GetData = new OsqarSQL();
// Update question name
GetData.InsertQuestions(QuestionName.Text, QuestionnaireId);
} // End NewQNRButton_Click
public void BindParentDataList(int QuestionnaireID)
{
_productConn = new SqlConnection();
_productConnectionString += "data source=mssql.myurl.com; Initial Catalog=database_2;User ID=userid;Password=aba123";
_productConn.ConnectionString = _productConnectionString;
SqlCommand myCommand = new SqlCommand("GetQuestion", _productConn);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.Add(new SqlParameter("#QUEST_ID", SqlDbType.Int));
myCommand.Parameters[0].Value = QuestionnaireID;
// check the connection state and open it accordingly.
_productConn.Open();
// Sql datareader object to read the stream of rows from SQL Server Database
SqlDataReader myDataReader = myCommand.ExecuteReader();
// Pass the Sql DataReader object to the DataSource property
// of DataList control to render the list of items.
dgQuestionnaire.DataSource = myDataReader;
dgQuestionnaire.DataBind();
// close the Sql DataReader object
myDataReader.Close();
// check the connection state and close it accordingly.
if (_productConn.State == ConnectionState.Open)
_productConn.Close();
// foreach loop over each item of DataList control
foreach (DataListItem Item in dgQuestionnaire.Items)
{
BindNestedDataList(Item.ItemIndex);
}
}
public void BindNestedDataList(int ItemIndex)
{
int QuestionID = Convert.ToInt32(dgQuestionnaire.DataKeys[ItemIndex]);
SqlCommand myCommand = new SqlCommand("GetAnswer", _productConn);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.Add("#QUESTION_ID", SqlDbType.Int).Value = QuestionID;
// check the connection state and open it accordingly.
if (_productConn.State == ConnectionState.Closed)
_productConn.Open();
// Sql datareader object to read the stream of rows from SQL Server Database
SqlDataReader myDataReader = myCommand.ExecuteReader();
// findControl function to get the nested datalist control
DataList nestedDataList = (DataList)dgQuestionnaire.Items[ItemIndex].FindControl("nestedDataList");
nestedDataList.DataSource = myDataReader;
nestedDataList.DataBind();
// close the Sql DataReader object
myDataReader.Close();
// check the connection state and close it accordingly.
if (_productConn.State == ConnectionState.Open)
_productConn.Close();
}
How can I get the value of a textbox when its corresponding button "updateName" is pressed?
Thanks
You can try doing something like this (code updated):
protected void UpdateQuestionName_Click(object sender, EventArgs e)
{
int QuestionnaireId = (int)Session["qID"];
GetData = new OsqarSQL();
//get the button that caused the event
Button btn = (sender as Button);
if (btn != null)
{
//here's you question text box if you need it
TextBox questionTextBox = (btn.Parent.FindControl("QuestionName") as TextBox);
// Update question name
GetData.InsertQuestions(questionTextBox.Text, QuestionnaireId);
//and in case you want more of the associated controls
//here's your data list with text boxes
DataList answersDataList = (btn.Parent.FindControl("nestedDataList") as DataList);
//and if answersDataList != null, you can use answersDataList.Controls to access the child controls, where answer text boxes are
}
} // End NewQNRButton_Click
This should work as you want.
Related
i'm building a web form that show Database's item(Tables, Rows, FK,...)
I have a CheckBoxList of Tables (chkListTable) which will show a new CheckBoxList of Rows (chkListRow) everytime I SelectedIndexChanged from chkListTable. The problem is i can show the items from chkListTable with 1 selected item. But i don't know how to show chkListRow if multiple item from chkListTable are selected.
Here are my codes:
aspx:
<div>
<asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label>
<asp:CheckBoxList ID="chkListTable" runat="server"
DataTextField="name"
DataValueFeild="name"
AutoPostBack="true"
OnSelectedIndexChanged="chkListTable_SelectedIndexChanged">
</asp:CheckBoxList>
</div>
<div>
<asp:CheckBoxList ID="chkListRow" runat="server"
DataTextField="COLUMN_NAME"
DataValueField="COLUMN_NAME"
RepeatDirection="Horizontal">
</asp:CheckBoxList>
</div>
aspx.cs:
protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e)
{
tableName.Clear();
foreach (ListItem item in chkListTable.Items)
{
if(item.Selected)
{
tableName.Add(item.Text.Trim());
}
}
for(int i = 0; i < tableName.Count; i++)
{
String query = "USE " + dbname +
" SELECT * FROM information_schema.columns" +
" WHERE table_name = '" + tableName[i] + "'" +
" AND COLUMN_NAME != 'rowguid'";
chkListRow.DataSource = Program.ExecSqlDataReader(query);
chkListRow.DataBind();
Program.conn.Close();
}
}
Program.cs:
public static bool Connect()
{
if (Program.conn != null && Program.conn.State == ConnectionState.Open)
Program.conn.Close();
try
{
Program.conn.ConnectionString = Program.constr;
Program.conn.Open();
return true;
}
catch (Exception e)
{
return false;
}
}
public static SqlDataReader ExecSqlDataReader(String query)
{
SqlDataReader myreader;
SqlCommand sqlcmd = new SqlCommand(query, Program.conn);
sqlcmd.CommandType = CommandType.Text;
if (Program.conn.State == ConnectionState.Closed) Program.conn.Open();
try
{
myreader = sqlcmd.ExecuteReader();
return myreader;
myreader.Close();
}
catch (SqlException ex)
{
Program.conn.Close();
return null;
}
}
I want my display to be like this:
[x]Table1 [x]Table2 [ ]Table3
[ ]Row1(Table1) [ ]Row2(Table1) [ ]Row3(Table1)
[ ]Row1(Table2) [ ]Row2(Table2)
Ok, this is a rather cute little problem.
So, if we select 1 table, then we need to have one "child" or so called ONE check box list.
but, if we select 2 tables, (or 5), then we need 2 (or 5) child check box lists.
In other words, we would not use the same check box list (child), or try to "mangle" that "N" number of check box lists we need.
So, this "child" sets (one for each checked table) is NOT known ahead of time.
So, we have "repeating" set of those child check box lists, right?
So, we can (and should) then use a "repeater". All a repeater does is "repeat" the whatever we want, and we "feed" the repeater the main list of tables.
So, our markup will now look like this:
<style>
.rBut input {margin-right: 5px; }
.rBut label {margin-right: 15px; }
</style>
<asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label>
<div class="rBut">
<asp:CheckBoxList ID="chkListTable" runat="server"
DataTextField="TABLE_NAME"
DataValueFeild="TABLE_NAME"
AutoPostBack="true" RepeatDirection="Horizontal" OnSelectedIndexChanged="chkListTable_SelectedIndexChanged" >
</asp:CheckBoxList>
</div>
</div>
<div>
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
Table: <%# Eval("Table") %> -
<div class="rBut">
<asp:CheckBoxList ID="chkListRow" runat="server"
RepeatDirection="Horizontal">
</asp:CheckBoxList>
</div>
</ItemTemplate>
</asp:Repeater>
Note for the 2nd repeter, we do NOT set the Value and text columns - WE DO NOT know them yet. You did not mention which columns to display, but most of my tables always have a PK "ID" for the first column, so lets make that the value , and the display (DataTextField, the 2nd column in the given table).
So, now we build up a "list" of the first selections, (tables), and then pass that thing to the repeater, and it will repeat.
the code now looks like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadData();
}
void LoadData()
{
string strSQL = "SELECT TABLE_NAME FROM VideoGames.INFORMATION_SCHEMA.TABLES " +
"WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME";
chkListTable.DataSource = MyRst(strSQL);
chkListTable.DataBind();
}
protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable MyTables = new DataTable();
MyTables.Columns.Add("Table", typeof(string));
foreach (ListItem OneTable in chkListTable.Items)
{
if (OneTable.Selected)
{
DataRow OneRow = MyTables.NewRow();
OneRow["Table"] = OneTable.Value;
MyTables.Rows.Add(OneRow);
}
}
// ok, we have a list of tables, send that to repeater
Repeater1.DataSource = MyTables;
Repeater1.DataBind();
}
public DataTable MyRst(string strSQL)
{
var rst = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.VideoGames))
{
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rst.Load(cmdSQL.ExecuteReader());
}
}
return rst;
}
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item
| e.Item.ItemType == ListItemType.AlternatingItem)
{
DataRowView rItem = e.Item.DataItem as DataRowView; // get binding data row
CheckBoxList chkListRow = e.Item.FindControl("chkListRow") as CheckBoxList;
string strSQL = "SELECT * FROM " + rItem["Table"].ToString();
DataTable MyTable = MyRst(strSQL);
chkListRow.DataValueField = MyTable.Columns[0].ColumnName;
chkListRow.DataTextField = MyTable.Columns[1].ColumnName;
chkListRow.DataSource = MyRst(strSQL);
chkListRow.DataBind();
}
}
So, now we see this:
If I click one, then I see this:
But, say I click 3, then I see this:
So, note how I feed the Repeater a table (could have been sql query, but in this case, we create table in code). Pass it to repeater.
For each table, the itemdatabound triggers. Because there are multiple copies of the tables, then we need to use find control.
And if you wanted to test/get all of the checked items, then we do a for each on the Repeater items - and again use find control to get each check box control.
But note how we only have two check box lists, but the 2nd one is inside of that repeater, and is data driven.
As a result, this will work for 1, or "N" tables.
I have a table for projects that has a bit value for whether the project is still active or not. I created a stored procedure that pulls the project name and the value for the project (0 for inactive, 1 for active). When I display it on my webpage, the bit values show up in checkboxes (which is good because I would like to be able to update those values with a button).
The problem is that I'm unable to click or unclick them.
How could I pull my data correctly so that the checkboxes for the project name is clickable to be updated?
Any help would be much appreciated.
public void loadProj()
{
SqlConnection con;
DataTable dt = new DataTable();
string CS = ConfigurationManager.ConnectionStrings["ProjDB"].ConnectionString;
using (con = new SqlConnection(CS))
{
con.Open();
SqlCommand cmd = new SqlCommand("GetProjActive", con);
SqlDataAdapter sa = new SqlDataAdapter(cmd);
callStoredProcedure(cmd, sa);
sa.Fill(dt);
GridView.DataSource = dt;
GridView.DataBind();
}
}
You need to set up a asp:TemplateField in your GridView columns, with a asp:CheckBox control inside this template.
Setting the CheckBox value: The Boolean database value should be bound into the CheckBox using the OnRowDataBound event.
Changing the database value: Register a OnCheckedChanged event on the template field's CheckBox control.
HTML markup:
<asp:GridView ID="gv"
runat="server"
DataSourceID="..."
OnRowDataBound="gv_DataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chk_selection" runat="server" OnCheckedChanged="chk_selection__CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
....
</Columns>
</asp:GridView>
Code behind:
protected void gv_DataBound(object sender, GridViewRowEventArgs e)
{
// Get this row's CheckBox control
CheckBox chkSelector = (CheckBox)e.Row.FindControl("chk_selection");
// Cast the database boolean value and set the checkbox's Checked property
chkSelector.Checked = Convert.ToBoolean(DataBinder.Eval(e.Row.DataItem, "bool_field"));
}
protected void chk_selection__CheckedChanged(object sender, EventArgs e)
{
// Update your database
}
I have drop-down inside of a gridview so when the gridview is loaded and the drop-down is bound then the drop-down only show the first value of the drop-down list and it is not showing the previously selected value. When the gridview loads, i would like the drop-down to show what was previously selected for that row. Here is my code:
aspx markup for the drop-down:
<asp:TemplateField HeaderText="Answer">
<ItemTemplate>
<asp:Label ID="lblAns" runat="server" Text='<%# Eval("DDL_ANS")%>' Visible="false"></asp:Label>
<asp:DropDownList ID="ddl_Answer" runat="server">
</asp:DropDownList>
</ItemTemplate>
Here is code behind:
protected void RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl_Answer;
//get current index selected
int current_quest = Convert.ToInt32(GridView1.DataKeys[e.Row.RowIndex].Value);
ddl_Answer = e.Row.FindControl("ddl_Answer") as DropDownList;
using (SqlConnection con2 = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["myconnection"].ConnectionString))
{
con2.Open();
using (SqlCommand cmd1 = new SqlCommand("select distinct DD_ANSWER from table1 where ID= '" + current_quest + "' ", con2))
{
ddl_Answer.DataSource = cmd1.ExecuteReader();
ddl_Answer.DataTextField = "DD_ANSWER";
ddl_Answer.DataValueField = "DD_ANSWER";
ddl_Answer.DataBind();
}
con2.Close();
}
}
I have tried to add this line of code after binding but i get this error "Object reference not set to an instance of an object"
ddl_Answer.Items.FindByValue((e.Row.FindControl("lblAns") as Label).Text).Selected = true;
thanks
I believe in your SELECT you need to use current_quest_sk instead of current_quest
Aslo try to check for null before accessing your controls:
var ddl_Answer = e.Row.FindControl("ddl_Answer") as DropDownList;
var answerLabel = e.Row.FindControl("lblAns") as Label;
if(answerLabel !=null && ddl_Answer!=null)
{
ddl_Answer.Items.FindByValue(answerLabel.Text).Selected = true;
}
#afzalulh has a valid point remove quotes if current_quest_sk(ID) is an Integer in your table.
You should avoid SQL injection but that's a different topic.
Place a breakpoint in your code, and setup through it with your debugger.
Either you have a typo in one of your string names or you are looking at the wrong control.
Stepping through your code will help you see exactly what line of your code is causing the problem.
You could also put a try/catch block around the whole thing to help you isolate the problem. Once you find the problem, remove the try/catch block.
I have a CheckBox in GridView cell. I want to update the database on CheckBox change, like when I unchecked it, 'Status' column in table update as false or vice versa.
Your question is very incomplete. But i'll give it a try, maybe it's helpful anyway.
Assuming you want to update as soon as the Checked state has changed(the user clicked the CheckBox), you have to set AutoPostBack="true" first.
Then you can handle the CheckBox.CheckedChanged event:
protected void Check_Clicked(Object sender, EventArgs e)
{
// get the checkbox reference
CheckBox chk = (CheckBox)sender;
// get the GridViewRow reference
GridViewRow row = (GridViewRow) chk.NamingContainer;
// assuming the primary key value is stored in a hiddenfield with ID="HiddenID"
HiddenField hiddenID = (HiddenField) row.FindControl("HiddenID");
string sql = "UPDATE dbo.Table SET Status=#Status WHERE idColumn=#ID";
using (var con = new SqlConnection(connectionString))
using (var updateCommand = new SqlCommand(sql, con))
{
updateCommand.Parameters.AddWithValue("#ID", int.Parse(hiddenID.Value));
// assuming the type of the column is bit(boolean)
updateCommand.Parameters.AddWithValue("#Status", chk.Checked);
con.Open();
int updated = updateCommand.ExecuteNonQuery();
}
}
Grid source
<asp:TemplateField HeaderText="View">
<ItemTemplate>
<asp:CheckBox ID="chkview" runat="server" AutoPostBack="true" OnCheckedChanged="chkview_CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
C# code
protected void chkview_CheckedChanged(object sender, EventArgs e)
{
// code here.
}
I have a follow dropdown list in my aspx page:
<asp:DropDownList ID="OrderPeriodStatus" runat="server" AutoPostBack="true"
CssClass="ddlb" Width="100px" Height="30px" DataSourceID="SqlDataSource5"
DataTextField="OrderPeriod" DataValueField="OrderPeriodID" onselectedindexchanged="OrderPeriodStatus_SelectedIndexChanged">
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource5" runat="server" ConnectionString="<%$ ConnectionStrings:ProdDB %> # blah blah query
</asp:SqlDataSource>
I tried to access the value of selected value in C# by following code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ProcessEligibleScenarios();
LoadOptions();
ddlbPeriod.DataBind();
GridView1.DataBind();
gvActiveLogs.DataBind();
}
}
protected void OrderPeriodStatus_SelectedIndexChanged(object sender, EventArgs e)
{
if (OrderPeriodStatus.SelectedValue != null)
{
SqlConnection myConn = default(SqlConnection);
SqlCommand myComm = default(SqlCommand);
myConn = new SqlConnection(ConfigurationManager.ConnectionStrings["ProdDB"].ConnectionString);
myConn.Open();
myComm = new SqlCommand("SELECT OrderPeriodDate, OrderPeriodStatus, Notes FROM OrderPeriod WHERE OrderPeriod ='" + OrderPeriodStatus.SelectedValue + "'");
try
{
myComm.Connection = myConn;
SqlDataReader Dr = myComm.ExecuteReader();
while (Dr.Read())
{
System.Diagnostics.Debug.Write("While reading the data");
TextBox1.Text = Dr["OrderPeriodDate"].ToString();
TextBox2.Text = Dr["OrderPeriodStatus"].ToString();
NotesArea.Value = (string)Dr["Notes"];
System.Diagnostics.Debug.WriteLine(OrderPeriodStatus.SelectedValue);
}
Dr.Close();
myConn.Close();
}
catch (SqlException sqx)
{
}
GridView1.DataBind();
}
else { }
}
But when i print the value. It shows the selected Index not the value. Why?
You have mismatch error on sqdatasource, replace with SqlDataSource4
DataSourceID="SqlDataSource5" <---
<asp:SqlDataSource ID="SqlDataSource4" runat="server" ConnectionString="<%$ ConnectionStrings:ProdDB %> # blah blah query
</asp:SqlDataSource>
You can try get the value from Request.Form object and to get the text use ddl.Items.FindByValue method
var value = Request.Form[DropDownListnew.UniqeID];
var text = DropDownListnew.Items.FindByValue(value);
If you set AutoPostback property on the dropdownlist to true, and ViewStateMode to inherit, you should get value you selected. I tried it on my side, and it worked. Since you already have SqlDataSource, and the DataSourceId of the dropdownlist is set to the SqlDataSource, it should be populated automatically.
---edit
Sorry, I think I might have misread your question. If you instead use
DropDownListnew.SelectedItem.Text
you should get the text value you want.
-- another edit:
#Amit, you will get index from SelectedValue, because in your dropdownlist code, you have set
DataValueField="OrderPeriodID"
which is basically your primary key or index. To get the text value instead of index you have to use
SelectedItem.Text
Also in your query:
myComm = new SqlCommand("SELECT OrderPeriodDate, OrderPeriodStatus, Notes FROM OrderPeriod WHERE OrderPeriod ='" + OrderPeriodStatus.SelectedValue + "'");
I think you should be using
WHERE OrderPeriodID ='" + OrderPeriodStatus.SelectedValue + "'");
You are missing the ID bit after OrderPeriod.