I am trying to display rows from my database based on the primary key when the select button is clicked.
<asp:Panel ID="pnlView" runat="server">
<p>
<asp:Label ID="lblTitle" runat="server" Text="Label"></asp:Label></p>
<p>
<asp:Label ID="lblBody" runat="server" Text="Label"></asp:Label></p>
</asp:Panel>
<asp:GridView ID="GridView1" runat="server" DataSourceID="sdsDocuments" EnableModelValidation="True"
SelectedIndex="0" OnSelectedIndexChanged="GridView1_SelectedIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" />
</Columns>
</asp:GridView>
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
lblTitle.Text = GridView1.SelectedRow.ToString();
lblBody.Text = GridView1.SelectedIndex.ToString();
SqlConnection thisConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["blcDocumentationConnectionString"].ConnectionString);
// Create Command Object
SqlCommand nonqueryCommand = thisConnection.CreateCommand();
try
{
// Open Connection
thisConnection.Open();
// Create INSERT statement with named parms
nonqueryCommand.CommandText = "SELECT DocumentTitle,DocumentBody FROM tblDocument WHERE DocumentID = #DocumentID";
// Add parms to Command parms collection
nonqueryCommand.Parameters.Add("#DocumentID", SqlDbType.Int);
// Execute query statement
nonqueryCommand.ExecuteNonQuery();
}
catch (SqlException ex)
{
}
finally
{
// Close Connection
thisConnection.Close();
}
In the GridView1_SelectedIndexChanged event, I can't see that you have set value for your parameter #DocumentID
Replace this nonqueryCommand.Parameters.Add("#DocumentID", SqlDbType.Int);
with this one nonqueryCommand.Parameters.AddWithValue("#DocumentID", GridView1.SelectedValue);
Edit: Following your comment, that you also need to display the text in your label, do like...
GridViewRow row = GridView1.SelectedRow;
lblTitle.Text = row.Cells[TitleCellIndex].Text;
lblBody.Text = row.Cells[BodyCellIndex].Text
You are not passing a value in to your SQL parameter for the documentid. If you have your grid populated correctly, the current row value is inside the EventArgs e variable.
Related
Basically whenever i would press a button on my website it would generate some kind of report with the ID and other information. What am trying to do is change one column of the table with SQL statements. I managed to change it but the code changes the column for all the IDs. What am trying to do is change column according to ID, but am still new to C# and SQL so i'm not sure how to get the automatic generated row. Just to highlight that i'm using a button in a gridview to change the value in the column. Below is what i tried:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
string order = Request.QueryString["id"];
SqlConnection con = new SqlConnection();
con.ConnectionString = ConfigurationManager.ConnectionStrings["RCManiaConnectionString"].ConnectionString;
con.Open();
if (e.CommandName == "received")
{
SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandText = "UPDATE [Orders] SET Status = 'Received' WHERE [ID] ='" + order + "'";
SqlDataReader data = com.ExecuteReader();
}
}
Using DataKeyNames property of grid view you can pass each record's primary key value, assign the same to the button of the record under CommandArgument. The below code is working code. You can try the same.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
DataKeyNames="ID" OnRowDataBound="GridView1_RowCommand">
<EmptyDataTemplate>
No Data Found
</EmptyDataTemplate>
<Columns>
<asp:TemplateField HeaderText="Update" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:ImageButton ID="btnUpdate" runat="server" CausesValidation="false" OnClick="btnUpdate_Click" CommandName="Select" ImageUrl="~/Contents/Images/classicPencil.svg" Width="20" Height="20" Text="View" CommandArgument='<%#Eval("ID")%>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
//Using Direct button click event
protected void btnUpdate_Click(object sender, ImageClickEventArgs e)
{
ImageButton btn = sender as ImageButton;
int ID = Convert.ToInt32(btn.CommandArgument);
//Your code of update data process
}
//Using grid row command event.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
int id = Convert.ToInt32(e.CommandArgument.ToString());
//Your code of update data process
}
I am able to retrieve out data from database to show which is Y and N using checkbox in gridview. However now i want to to able to store which checkbox is checked back into the database after editing.
What i did so far:
.aspx
<asp:GridView ID="SiteGridView" runat="server" CssClass="datagrid"
GridLines="Vertical" AutoGenerateColumns="False"
Width="100%"
AllowPaging="True" AllowSorting="True"
DataKeyNames="promoID" OnRowCommand="GvPage_RowCommand"
OnPageIndexChanging="GvPage_PageIndexChanging"
OnSorting="GvPage_Sorting"
OnRowDatabound="SiteGridView_RowDataBound"
OnRowEditing="SiteGridView_RowEditing">
<Columns>
<asp:TemplateField HeaderText="Default">
<ItemTemplate>
<asp:CheckBox ID="process_flag" runat="server"
Checked='<%# bool.Parse(Eval("PROCESSED").ToString()) %>'
Enable='<%# !bool.Parse(Eval("PROCESSED").ToString()) %>' />
</ItemTemplate>
<ItemStyle Width="20%" />
</asp:TemplateField>
</Columns>
</asp:GridView>
CodeBehind:
SqlCommand cmd = new SqlCommand("SELECT * , CAST(CASE defaults WHEN 'Y' THEN 1 ELSE 0 END AS BIT) AS PROCESSED FROM Promotions");
SqlDataAdapter da = new SqlDataAdapter();
DataTable dt = new DataTable();
da.SelectCommand = cmd;
// Save results of select statement into a datatable
da.Fill(dt);
SiteGridView.DataSource = dt;
SiteGridView.DataBind();
protected void SiteGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//check userrole & display accrodingly
if (Session["ROLE"].ToString() != "SA")
{
//ImageButton btnEdit = (ImageButton)e.Row.FindControl("btnDelete");
//btnEdit.Visible = false;
SiteGridView.Columns[4].Visible = false;
}
}
}
Have you tried:
Checked='<%# Eval("PROCESSED")%>'
If so, what error messages have you gotten?
For some reason Checkboxes do not trigger GridView RowCommand events. It probably can be done with appropriate calls to ClientScript.GetPostBackEventReference(), but thats a whole other level of complexity. So, in order to act on a CheckBox click and handle events individually:
(NB: I've stripped out much of your coding to clarify my points.)
In your CheckBox set AutoPostBack="true"
Add a handler for OnCheckedChanged.
Make sure the DataKey contains the pk of the row you need to update with the CheckBox State
// Simplified version of your markup
<asp:GridView ID="SiteGridView" runat="server"
DataKeyNames="promoID"
OnRowDataBound="SiteGridView_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Default">
<ItemTemplate>
<asp:CheckBox ID="process_flag" runat="server"
Checked='<%# bool.Parse(Eval("PROCESSED").ToString()) %>'
Enable='<%# !bool.Parse(Eval("PROCESSED").ToString()) %>'
OnCheckedChanged="process_flag_CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
In the RowDataBound event, find the CheckBox and add the Row Index as an attribute
// Merge this with your `RowDataBound` event
protected void SiteGridView_RowDataBound( object sender, GridViewRowEventArgs e ) {
if ( e.Row.RowType == DataControlRowType.DataRow ) {
CheckBox cbx = ( CheckBox ) e.Row.FindControl( "CheckBox1" );
cbx.Attributes[ "data-row-idx" ] = e.Row.RowIndex.ToString();
}
}
Handle the CheckChanged event:
// Add this handler to your code
protected void process_flag_CheckedChanged( object sender, EventArgs e )
{
CheckBox cbx = ( CheckBox ) sender;
Int32 rowidx = Convert.ToInt32(cbx.Attributes["data-row-idx"]);
Int32 pk = (Int32) GridView4.DataKeys[rowidx].Value;
// simple way to see event arguments before actually touching the database
GridView4.Caption = string.Format(
"CheckChanged: Row {0}, State: {1}, RowPK: {2} ", rowidx , (cbx.Checked ? "Checked" : "Unchecked"), pk );
// Save Data and rebind the gridview to reflect changes
// Verify your parameters before attempting an actual update
// YourDatabaseCallWithAppropriateParamaters( ... );
GridView1.DataBind();
}
First of all use a foreach loop to findout which rows are checked. Then store ID of those rows in a List.
foreach (GridViewRow row in SiteGridView.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
CheckBox chkRow = (row.Cells[0].FindControl("process_flag") as CheckBox);
if (chkRow.Checked)
{
string ID = row.Cells[columnID].Text;
I'm displaying a datatable that selects a number of elements from the database (IncomingsId, Type, Cost, Frequency) and I'm not sure how to delete a row when a button is clicked.
I've tried many solutions so far but nothing is working.
Here is the button I have within my Grid view
<asp:TemplateField HeaderText="Delete">
<ItemTemplate>
<asp:button id="DeleteRowButton" text="Delete Record" onclick="DeleteRowButton_Click" runat="server"/>
</ItemTemplate>
</asp:TemplateField>
And here is the code behind this page were I am creating the datatable.
SqlConnection con;
public _Default()
{
con = new SqlConnection(#"MySQLConnection");
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DisplayRecord();
}
}
public DataTable DisplayRecord()
{
string userId = (HttpContext.Current.User.Identity.GetUserId());
SqlDataAdapter Adp = new SqlDataAdapter("select * from Incomings where AspNetUsersId = '" + userId +"'", con);
DataTable Dt = new DataTable();
Dt.AcceptChanges();
Adp.Fill(Dt);
grid1.DataSource = Dt;
grid1.DataBind();
return Dt;
}
public void DeleteRowButton_Click(object sender, EventArgs e)
{
}
Cheers in advance for any help. I'm sure it's a simple resolution
You need a way for your code to know which ID to delete. Here is how I would normally do it:
Replace your button with an ItemTemplate, and add the button in here instead:
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button Text="Delete" runat="server" CommandArgument='<%# Eval("userId") %>' CommandName="Delete" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
When you have the button this way, you now have access to a CommandArgument and CommandName attributes. Notice the argument I am passing is Eval("userId"), the command name (as you will see later) is used to recognize what action you want to execute (this could be anything, is just a name).
Replace the CommandArgument with whatever value(s) you want to pass to the server, using the name that came from the database/datasource (I am guessing it would be userId).
Then, to capture this you need to implement the RowCommand event of the GridView, and intercept the correct CommandName:
public void GridView1_RowCommand(Object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
string userId = e.CommandArgument.ToString();
//do something with the id
}
}
Here you have to make sure the CommandName in your button, matches to whatever action you want to execute in the RowCommand. This should do the trick.
Don't forget to bind the event to your GridView:
<asp:GridView OnRowCommand="GridView1_RowCommand" ID="GridView1" runat="server">
...
</asp:GridView>
just use this for the front-end code
<asp:GridView ID="grid1" OnRowDeleting="OnRowDeleting" DataKeyNames="deleteR" runat="server" AutoGenerateColumns="False" CellPadding="4" GridLines="None" style="width:100%" >
<columns>
<asp:TemplateField HeaderText="Delete Row">
<ItemTemplate>
<asp:Button ID="btnDelete" runat="server" class="btn btn-primary" Text="Delete" CommandName="Delete" OnRowDataBound="OnRowDataBound" />
</ItemTemplate>
</asp:TemplateField>
And have this in behind it:
protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
int deleteR= Convert.ToInt32(grid1.DataKeys[e.RowIndex].Values[0]);
//have a sql statement here that add's the parameter ID for the row you want to delete, something like
SqlCommand com = new SqlCommand ("Delete FROM yourdatabase Where yourID = #yourID"
com.Parameters.AddWithValue("#yourID", yourID)
}
What you're looking for is indeed a simple solution.
You can use a foreach loop to search all DataRows within the DataTable for some kind of ID.Here's an example of what I mean:
String s = "/* IncomingsId for what you want to delete */";
foreach (DataRow r in dt.Rows) {
if (r["IncomingsId"].ToString().Equals(s)) {
dt.Rows.Remove(r);
}
}
Just a quick update for anyone that's helped me, thanks for your advice.
Asp.Net has it's own built in AutoGenerateDeleteButton and I set that to true and ran a bit of code behind it.
A simple solution that really shouldn't have taken me all day to complete!
i have gridview contains linkbutton as below cod in my aspx file:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="Button3" Style="float: left; margin-left: 10px"
CommandArgument='<%# Bind("ID") %>'
Text="cancellation" runat="server" CommandName="cancell" OnClick="Button3_Click">
<i aria-hidden="true" class="icon-lock" title="cancellation"></i>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
I want when user click on link button update my database table but when I want get value of cell from gridview selected row I face by null refrence exception in line: string barcode = dgvData.SelectedRow.Cells[12].Text;.
protected void Button3_Click(object sender, EventArgs e)
{
Transaction tr = new Transaction();
HasinReservation.Entities.Db.Transaction dt = new Transaction();
SqlConnection connection = new SqlConnection(#"Data Source=192.x.x.x\Sql2008;Initial Catalog=GardeshgariKish;User ID=cms;Password=******;MultipleActiveResultSets=True;Application Name=EntityFramework");
connection.Open();
SqlCommand sqlCmd = new SqlCommand("Update Transactions SET IsCancelled = 1 WHERE BarCodeNumber = #Value", connection);
string barcode = dgvData.SelectedRow.Cells[12].Text;
sqlCmd.Parameters.AddWithValue("#Value", barcode);
//sqlCmd.Parameters.AddWithValue("#Value2", DropDownList2.SelectedItem.Text);
sqlCmd.ExecuteNonQuery();
connection.Close();
}
dgvData.SelectedRow won't give you the row from which the button was clicked. You need NamingContainer for that. This should work for you:-
LinkButton Button3 = (LinkButton)sender;
GridViewRow selectedRow = (GridViewRow)Button3.NamingContainer;
string barcode = selectedRow.Cells[12].Text;
You can try this way to get the value from GridView. I'm not writing the entire code of yours but the error containing part.
protected void Button3_Click(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0)
{
DataGridViewRow row = this.Rows[e.RowIndex];
string barcode = row.Cells["ID"].Value.ToString();
}
}
But what I can see from Your code that You're using edit mode of GridView but not leveraging it into Your code. Please see this link to To Edit And Update Rows In GridView In Asp.Net.
GridView.SelectedRow property will be populated with the row only when you select a row. Easiest way is to set the Property autogenerateselectbutton to true as:
<asp:gridview id="CustomersGridView" autogenerateselectbutton="True" .../>
You must perform the below steps sequentially:
Select a row by clicking the Select Button
After that click the Link button. In the Button Click event now you will have your selected row as usual.
Also, dgvData.SelectedRow.Cells[12].Text means the Cell/Column 12 should be a BoundField.
If Column 12 is Template Field, use the FindControl() method as dgvData.SelectedRow.FindControl("lblBarCode") as Label).Text; assuming a Label is used to display bar code etc...
that's because you are not using the select-command
the way to go should be:
Add the RowCommand Event to your GridView
onrowcommand="GridView1_RowCommand"
replace the Command Argument id with BarCode and remove OnClick="Button3_Click"
<asp:LinkButton ID="Button3" CommandArgument='<%# Bind("BarCode")
receive the value
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "cancell")
{
string barcode = e.CommandArgument;
}
}
thank you for your concern i found it.
here is my edited asp markup:
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="Button3" Style="float: left; margin-left: 10px"
CommandArgument='<%# Bind("ID") %>'
Text="cancellation" runat="server" **CommandName="select"** OnClick="Button3_Click">
<i aria-hidden="true" class="icon-lock" title="cancellation"></i>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
and here is code behind:
protected void Button3_Click(object sender, EventArgs e)
{
Transaction tr = new Transaction();
**GridViewRow clickedRow = ((LinkButton)sender).NamingContainer as GridViewRow;**
HasinReservation.Entities.Db.Transaction dt = new Transaction();
**int x = clickedRow.RowIndex;**
SqlConnection connection = new SqlConnection(#"Data Source=192.X.X.X\Sql2008;Initial Catalog=GardeshgariKish;User ID=cms;Password=XXXXXX;MultipleActiveResultSets=True;Application Name=EntityFramework");
connection.Open();
SqlCommand sqlCmd = new SqlCommand("Update Transactions SET IsCancelled = 1 WHERE BarCodeNumber = #Value", connection);
**string barcode = dgvData.Rows[x].Cells[12].Text;**
sqlCmd.Parameters.AddWithValue("#Value", barcode);
sqlCmd.ExecuteNonQuery();
connection.Close();
}
I a newbie to asp.net. I have created a DB table in sqlserver with 3 columns; ImageID, Filename & Score.
FileName is C:\pics\beads.png or C:\pics\moreimages\scenary.jpeg.
Using C# asp.net, I have created a GridView. This Gridview should populate
(column 1)ImageID and get the image from the Filename (column2) and I have 2 Checkboxlist created as shown below which should accept score for the images from user and save it into the DB table.
Question 1 .
I am able to populate Image ID, but Images are not getting populated.
Question 2.
I do not know how to access the checkboxlist since it is in template. The checked is in the default select and doesn't change even if I click on it. Which method/property should be used to do save the selection to the database. Here's my code
<form id="form1" runat="server">
<p style="height: 391px">
<asp:GridView ID="GridView1" runat="server" Caption="Logos" Height="299px" Width="577px" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="ImageID" HeaderText="ImageID" />
<asp:ImageField DataImageUrlField="FileName" ControlStyle-Width="100"
ControlStyle-Height="100" HeaderText="Image" AlternateText="No image">
<ControlStyle Height="100px" Width="100px"></ControlStyle>
</asp:ImageField>
<asp:TemplateField HeaderText="Score" AccessibleHeaderText="CheckBoxList" ValidateRequestMode="Enabled">
<ItemTemplate>
<asp:CheckBoxList runat="server" AutoPostBack="true" RepeatColumns="3" ID="test">
<asp:ListItem Selected="True" Value="5">Good</asp:ListItem>
<asp:ListItem Value="0">Not Good </asp:ListItem>
<asp:ListItem Value="3">OK</asp:ListItem>
</asp:CheckBoxList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Save" Width="130px" />
<asp:Button ID="Button2" runat="server" OnClientClick="javaScript:window.close(); return false;" Text="Exit" Width="102px" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</p>
</form>
public string sqlSel = #"SELECT TOP 3 [ImageID],FileName FROM [db1].[ImagesTest] where [Score] is null";
protected void Page_Load(object sender, EventArgs e)
{
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString))
{
connection.Open();
SqlCommand cmdSel = new SqlCommand(sqlSel, connection);
SqlDataReader reader1 = cmdSel.ExecuteReader();
while (reader1.Read())
{
DataSet ds = GetData(sqlSel);
if (ds.Tables.Count > 0)
{
GridView1.DataSource = ds;
GridView1.DataBind();
}
else
{
Response.Write("Unable to connect to the database.");
}
}
}
}
private DataSet GetData(string cmdSel)
{
String strConnString = System.Configuration.ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString;
DataSet ds = new DataSet();
try
{
SqlConnection con = new SqlConnection(strConnString);
SqlDataAdapter sda = new SqlDataAdapter(cmdSel,con);
sda.Fill(ds);
}
catch (Exception ex)
{
Response.Write("IN EXCEPTION "+ex.Message);
return null;
}
return ds;
}
Thanks for ur time
Rashmi
There are several issues with your code, here is what it should be fixed:
How to fix the images (Question 1)
As #Guilherme said in the comments, for images use URLs instead of disk paths.
Replace the images disk paths C:\pics\beads.png or C:\pics\moreimages\scenary.jpeg to something like Images/beads.png and Images/scenary.jpeg.
For this to work, you will need to have a folder named Images that contains these two files on the same directory level as your .aspx file.
Adjust your GridView1 declaration in the ASPX file
On your GridView1 declaration you should:
attach a handler to the OnRowDataBound event. This will allow you to properly bind the Score dataset column to the Score gridview column
set the DataKeyNames property on the grid to what should be the primary key for your images table (in this case DataKeyNames="ImageID")
use a RadioButtonList instead of a CheckboxList, because according to your dataset you can only set one value, which is what the RadioButtonList does. The CheckboxList is normally used when multiple selection is needed.
attach a handler to the SelectedIndexChanged event on the RadioButtonList. This will allow you to save the new values to the database (Question 2)
Here's how your GridView declaration should look like:
<asp:GridView ID="GridView1" runat="server" Caption="Logos" Height="299px" Width="577px" AutoGenerateColumns="False" OnRowDataBound="GridView1_RowDataBound" DataKeyNames="ImageID">
<Columns>
<asp:BoundField DataField="ImageID" HeaderText="ImageID" />
<asp:ImageField DataImageUrlField="FileName" ControlStyle-Width="100"
ControlStyle-Height="100" HeaderText="Image" AlternateText="No image">
<ControlStyle Height="100px" Width="100px"></ControlStyle>
</asp:ImageField>
<asp:TemplateField HeaderText="Score" AccessibleHeaderText="RadioButtonList" ValidateRequestMode="Enabled">
<ItemTemplate>
<asp:RadioButtonList runat="server" AutoPostBack="true" RepeatColumns="3" ID="test" OnSelectedIndexChanged="test_SelectedIndexChanged">
<asp:ListItem Value="5">Good</asp:ListItem>
<asp:ListItem Value="0">Not Good </asp:ListItem>
<asp:ListItem Value="3">OK</asp:ListItem>
</asp:RadioButtonList>
<!-- UPDATED! - keep the old values in a hidden field -->
<asp:HiddenField runat="server" ID="hfOldScore" Value='<%# Eval("Score") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Adjust your code behind value in your .ASPX.CS file (Question 2)
On the code behind, you will also need to:
Make sure you are binding to the GridView only once in the Page_Load event, by checking the IsPostBack property
(Optional, but recommended) Move the logic of getting data (with the SQLConnection code) in a separate method that will handle only data retrieval
Implement the handler for the OnRowDataBound event. This will bind any values from the Score column to the RadioButtonList control
Implement the handler for the SelectedIndexChecked event of the RadioButtonList control. This will allow you to save to the database the new values
Finally, here's the entire code-behind code:
protected void Page_Load(object sender, EventArgs e)
{
//bind only the first time the page loads
if (!IsPostBack)
{
DataSet ds = GetData(sqlSel);
if (ds.Tables.Count > 0)
{
GridView1.DataSource = ds;
GridView1.DataBind();
}
else
{
Response.Write("Unable to connect to the database.");
}
}
}
private DataSet GetData(string cmdSel)
{
//normally you should query the data from the DB
//I've manually constructed a DataSet for simplification purposes
DataSet ds = new DataSet();
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("ImageID", typeof(int)));
dt.Columns.Add(new DataColumn("FileName", typeof(string)));
dt.Columns.Add(new DataColumn("Score", typeof(int)));
dt.Rows.Add(100, #"Images/beads.png", 0);
dt.Rows.Add(200, #"Images/moreimages/scenary.jpeg", 3);
dt.Rows.Add(300, #"Images/moreimages/scenary.jpeg", 5);
ds.Tables.Add(dt);
return ds;
}
protected void Button1_Click(object sender, EventArgs e)
{
//UPDATED - iterate through all the data rows and build a dictionary of items
//to be saved
Dictionary<int, int> dataToUpdate = new Dictionary<int, int>();
foreach (GridViewRow row in GridView1.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
int imageID = (int)GridView1.DataKeys[row.RowIndex].Value;
int oldScore;
int newScore;
int.TryParse((row.FindControl("hfOldScore") as HiddenField).Value, out oldScore);
int.TryParse((row.FindControl("test") as RadioButtonList).SelectedValue, out newScore);
if (oldScore != newScore)
{
dataToUpdate.Add(imageID, newScore);
}
}
}
//update only the images that were changed
foreach (var keyValuePair in dataToUpdate)
{
SaveToDB(keyValuePair.Key, keyValuePair.Value);
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//we are only interested in the data Rows
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRow dataRow = (e.Row.DataItem as DataRowView).Row;
//manually bind the Score column to the RadioButtonlist
int? scoreId = dataRow["Score"] == DBNull.Value ? (int?)null : (int)dataRow["Score"];
if (scoreId.HasValue)
{
RadioButtonList test = e.Row.FindControl("test") as RadioButtonList;
test.ClearSelection();
test.SelectedValue = scoreId.Value.ToString();
}
}
}
protected void test_SelectedIndexChanged(object sender, EventArgs e)
{
RadioButtonList test = sender as RadioButtonList;
GridViewRow gridRow = test.NamingContainer as GridViewRow;
//obtain the current image Id
int imageId = (int)GridView1.DataKeys[gridRow.RowIndex].Value;
//obtain the current selection (we will take the first selected checkbox
int selectedValue = int.Parse(test.SelectedValue);
//UPDATED! - saves are now handled on the Save button click
//SaveToDB(imageId, selectedValue);
}
private void SaveToDB(int imageId, int score)
{
//UPDATED!
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
command.Parameters.Add("#ImageID", imageId);
command.Parameters.Add("#Score", score);
command.CommandText = #"update [db1].[ImagesTest] set Score = #Score where [ImageID] = #ImageID";
command.ExecuteNonQuery();
}
}
}
UPDATED!
The declaration of the GridView1 now contains a hidden field containing the Score value. You can use this hidden field to determine which row has changed, so you can trigger a save only on the changed ones
Save is now done on the click of the Save button, by iterating through the rows of the grid an building a Dictionary<int,string> to keep only the changes.
SaveToDB method should work, but I cannot test this myself.
Question 2:
To access your checkbox you can use.
GridViewRow row = GridView1.Rows[i];
CheckBox Ckbox = (CheckBox)row.FindControl("test");
For Question 1
Instead of ImageField you can use use ASP:Image in Templatefield like this
<asp:TemplateField HeaderText="Score" AccessibleHeaderText="CheckBoxList" ValidateRequestMode="Enabled">
<ItemTemplate>
<asp:Image ID="imageControl" runat="server" ImageUrl='<%# Eval("Filename") %>'></asp:Image>
</ItemTemplate>
</asp:TemplateField>
For Question 2
This is one of the example for how to access each Checkbox list inside gridview
For Each gvr As GridViewRow In Gridview1.Rows
If (CType(gvr.FindControl("CheckBox1"), CheckBox)).Checked = True Then
ReDim uPrimaryid(iCount)
uPrimaryid(iCount) = New Integer
uPrimaryid(iCount) = gvr.Cells("uPrimaryID").Text
iCount += 1
End If
Next