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
}
Related
I am currently creating an asp.net web app in C# using Visual Studio. I have a gridview that displays data from a database table and I have added the datasource manually in my .cs page as I have converted the childrens DOB into age, thus enabling me to filter the gridview with a dropdown list of age groups. This all works fine, the only issue i'm having is getting the delete link button to work. I need it to completely delete the child from the database table if clicked.
I began by going to the gridview in design mode, Add new column --> Button field (button type 'link', command name 'delete') and then adding the following code in my .cs page:
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
LinkButton lnkRemove = (LinkButton)sender;
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "delete from children where " +
"childID=#childID";
cmd.Parameters.Add("#childID", SqlDbType.VarChar).Value
= lnkRemove.CommandArgument;
GridView1.DataSource = source;
GridView1.DataBind();
}
When I run the page and click delete next to any of the children, I get the following error:
I will include the full code from my .cs page as well as my source code. Can someone help me figure out why I am getting the error and why the delete buttons wont delete without issue? Thanks in advance.
FULL .CS CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;
namespace Coursework
{
public partial class Testy1 : System.Web.UI.Page
{
//create a datasource
SqlDataSource source = new SqlDataSource();
protected void Page_Load(object sender, EventArgs e)
{
//always set some defaults for the sqldatasource
source.ID = "source1";
source.ConnectionString = ConfigurationManager.ConnectionStrings["newregDBConnectionString"].ConnectionString;
source.SelectCommand = "SELECT firstname, dob, DATEDIFF(hour, dob, GETDATE()) / 8766 AS age FROM children ORDER BY age";
if (!IsPostBack)
{
//bind the grid
GridView1.DataSource = source;
GridView1.DataBind();
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
//the new database query, now with where clause
source.SelectCommand = "SELECT firstname, dob, DATEDIFF(hour, dob, GETDATE()) / 8766 AS age FROM children WHERE (DATEDIFF(hour, dob, GETDATE()) / 8766 BETWEEN #start AND #end) ORDER BY age";
//get the end age from the dropdown and cast as int
int end = Convert.ToInt32(DropDownList1.SelectedValue);
//get the start int for the filter
int start = end - 2;
//if the filter is resetted, make sure the query returns all ages
if (end == 5)
{
start = 5;
end = 99;
}
//replace the parameters in the query
source.SelectParameters.Add("start", start.ToString());
source.SelectParameters.Add("end", end.ToString());
//rebind the grid
GridView1.DataSource = source;
GridView1.DataBind();
}
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
}
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
LinkButton lnkRemove = (LinkButton)sender;
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "delete from children where " +
"childID=#childID";
cmd.Parameters.Add("#childID", SqlDbType.VarChar).Value
= lnkRemove.CommandArgument;
GridView1.DataSource = source;
GridView1.DataBind();
}
}
SOURCE CODE:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Testy1.aspx.cs" Inherits="Coursework.Testy1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<p></p>
<p></p>
<p></p>
<p></p>
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
<asp:ListItem Text="Filter age" Value="5"></asp:ListItem>
<asp:ListItem Text="5 - 7" Value="7"></asp:ListItem>
<asp:ListItem Text="8 - 10" Value="10"></asp:ListItem>
<asp:ListItem Text="11 - 13" Value="13"></asp:ListItem>
<asp:ListItem Text="14 - 16" Value="16"></asp:ListItem>
</asp:DropDownList>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" OnRowDeleting="GridView1_RowDeleting" >
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<%# Eval("firstname") %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="DOB">
<ItemTemplate>
<%# Convert.ToDateTime(Eval("dob")).ToString("d MMMM yyyy") %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Age">
<ItemTemplate>
<%# Eval("age") %>
</ItemTemplate>
</asp:TemplateField>
<asp:ButtonField CommandName="Delete" Text="Delete" />
</Columns>
</asp:GridView>
</asp:Content>
The sender is the GridView in RowDeleting, not the button, so your cast fails.
If you would specify the DataKeyNames you could use the GridView's DataKeys property:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnSelectedIndexChanged="GridView1_SelectedIndexChanged"
DataKeyNames = "childID"
OnRowDeleting="GridView1_RowDeleting" >
Codebehind:
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
string childId = GridView1.DataKeys[e.RowIndex].Value.ToString();
string deleteSql = #"DELETE FROM Children
WHERE childID = #childID;";
using(var con = new SqlConnection(ConfigurationManager.ConnectionStrings["newregDBConnectionString"].ConnectionString))
using(var cmd = new SqlCommand(deleteSql, con))
{
cmd.Parameters.Add("#childID", SqlDbType.VarChar).Value = childId;
con.Open();
int deleted = cmd.ExecuteNonQuery();
}
GridView1.DataSource = GetDataSource(); // provide a method that returns it
GridView1.DataBind();
}
Well, you are handling GridView's Deleting event, not button's click. So your sender is actually a GridView control, you should not cast it to LinkButton.
Besides, you did not assign CommandArgument. Should be something like that:
<asp:ButtonField CommandName="Delete" Text="Delete" CommandArgument='<%# Eval("childID") %>' />
But even if you did, this is not going to help as CommandArgument is not passed along with Delete even args. Thus, you have two options.
First is to switch to handling RowCommand event:
OnRowDeleting="GridView1_RowCommand"
In there you need to check that command is actually a delete one, and use command arg to delete:
if (e.CommandName == "Delete")
{
// parse e.CommandArgument and delete
}
Second is to define primary keys for the rows.
DataKeyNames="childID"
This is going to be available via event args of Deleting event:
e.Keys
You do not need to set CommandArgument at all in this case.
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
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.