SQLDataSource DeleteCommand to get parameters - c#

I am having some problems passing parameters to a DELETE command, and cant seem to get a good understanding on how it works.
<asp:SqlDataSource ID="sdsPropertyList"
runat="server"
ProviderName="<%$ appSettings:ProviderName %>"
ConnectionString="<%$ appSettings:ConnectionString %>"
SelectCommand="selPropertyByAcntID"
SelectCommandType="StoredProcedure"
OnSelecting="sdsPropertyList_Selecting"
OnSelected="sdsPropertyList_Selected"
DeleteCommand="delPropertyByPropID"
DeleteCommandType="StoredProcedure"
OnDeleting="sdsPropertyList_Deleting"
OnDeleted="sdsPropertyList_Deleted">
<SelectParameters>
<asp:Parameter Name="in_acntID" Type="Int32" DefaultValue="0" />
</SelectParameters>
<DeleteParameters>
<asp:Parameter Name="in_acntID" Type="Int32" DefaultValue="0" />
<asp:Parameter Name="in_propID" Type="Int32" DefaultValue="0" />
</DeleteParameters>
</asp:SqlDataSource>
<asp:GridView ID="gvProperty" runat="server" DataSourceID="sdsPropertyList"
AutoGenerateColumns="false" CssClass="gvPropList">
<Columns>
<asp:BoundField HeaderText="ID" InsertVisible="true" DataField="prop_id" ReadOnly="true" Visible="False" />
<asp:BoundField HeaderText="Property" DataField="prop_title"
ItemStyle-CssClass="gvPropTitle" >
<ItemStyle CssClass="gvPropTitle" />
</asp:BoundField>
<asp:BoundField HeaderText="Units" DataField="unitCount"
ItemStyle-CssClass="gvUnitCount" >
<ItemStyle CssClass="gvUnitCount" />
</asp:BoundField>
<asp:BoundField DataField="prop_lastmodified" HeaderText="Last Modified"
ItemStyle-CssClass="gvDate" DataFormatString="{0:M/dd/yyyy hh:mm tt}" >
<ItemStyle CssClass="gvDate" />
</asp:BoundField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lbtnEdit" runat="server" CommandName="EditRecord" Text="Edit" CommandArgument='<%# Eval("prop_id") %>'></asp:LinkButton>
<asp:LinkButton ID="lbtnDelete" runat="server" CommandName="Delete" Text="Delete" CommandArgument='<%# Eval("prop_id") %>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lbtnAdd" runat="server" CommandName="AddRecord" Text="Add" CommandArgument='<%# Eval("prop_id") %>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="headerPropList"/>
<RowStyle CssClass="gvPropRow" />
</asp:GridView>
protected void sdsPropertyList_Selecting(object sender, SqlDataSourceSelectingEventArgs e)
{
int userID = Convert.ToInt32(Page.User.Identity.Name);
if (userID != 0)
e.Command.Parameters["in_acntID"].Value = userID;
}
protected void sdsPropertyList_Deleting(object sender, SqlDataSourceCommandEventArgs e)
{
int userID = Convert.ToInt32(Page.User.Identity.Name);
if (userID != 0)
{
e.Command.Parameters["in_acntID"].Value = userID;
}
}
The SELECT statement is straightforward which requires one input parameter of userID.
However, the DELETE statement, requires 2 parameter inputs.
in_acntID = userID
in_propID = the boundfield datafield prop_id
What am I doing wrong? and should the CommandName and CommandArgument be passed at the ItemTemplate level if I have it defined at the SqlDataSource level?
I want the delete button to achieve the following:
delete records from table(s) in DB
remove the row from the gridview
UPDATE
After some additional research, I've found that, the NAME for parameters and HeaderText for Boundfield must be the same so that the values within your gridview can be used by the SQL commands of the datasource.
With the exception of the initial select commant, i have removed all the code behind references.
All is working corrently now.

According to the MSDN documentation, you need to specify the DataKeyNames on the gridView:
"Use the DataKeyNames property to specify the field or fields that represent the primary key of the data source. You must set the DataKeyNames property in order for the automatic update and delete features of the GridView control to work. The values of these key fields are passed to the data source control in order to specify the row to update or delete."

e.g. if the id was in a listbox or dropdown
<DeleteParameters>
<asp:ControlParameter ControlID="controlname" Name="id" PropertyName="SelectedValue" Type="Int32" />
</DeleteParameters>
i have used the above successfully for deleting . this could work for textboxes or labels. If you are handling the event , why not just take the entire delete process to the even handler ? Specify the entire sql setup including connection , command execution there . This method has also worked for me .

After some additional research, I've found that, the NAME for parameters and HeaderText for Boundfield must be the same so that the values within your gridview can be used by the SQL commands of the datasource.
With the exception of the initial select commant, i have removed all the code behind references.
All is working corrently now.
<asp:SqlDataSource ID="sdsPropertyList"
runat="server"
ProviderName="<%$ appSettings:ProviderName %>"
ConnectionString="<%$ appSettings:ConnectionString %>"
SelectCommand="selPropertyByAcntID"
SelectCommandType="StoredProcedure"
OnSelecting="sdsPropertyList_Selecting"
DeleteCommand="delPropertyByPropID"
DeleteCommandType="StoredProcedure"
OnDeleted="sdsPropertyList_Deleted" >
<SelectParameters>
<asp:Parameter Name="acnt_id" Type="Int32" />
</SelectParameters>
<DeleteParameters>
<asp:Parameter Name="acnt_id" Type="Int32" />
<asp:Parameter Name="prop_id" Type="Int32" />
</DeleteParameters>
</asp:SqlDataSource>
<asp:GridView ID="gvProperty" runat="server" DataSourceID="sdsPropertyList"
AutoGenerateColumns="false" CssClass="gvPropList" DataKeyNames="acnt_id, prop_id">
<Columns>
<asp:BoundField HeaderText="acnt_id" InsertVisible="true" DataField="acnt_id" ReadOnly="true" Visible="False" />
<asp:BoundField HeaderText="prop_id" InsertVisible="true" DataField="prop_id" ReadOnly="true" Visible="False" />
<asp:BoundField HeaderText="Property" DataField="prop_title">
<ItemStyle CssClass="gvPropTitle" />
</asp:BoundField>
<asp:BoundField HeaderText="Units" DataField="unitCount" >
<ItemStyle CssClass="gvUnitCount" />
</asp:BoundField>
<asp:BoundField DataField="prop_lastmodified" HeaderText="Last Modified"
ItemStyle-CssClass="gvDate" DataFormatString="{0:M/dd/yyyy hh:mm tt}" >
<ItemStyle CssClass="gvDate" />
</asp:BoundField>
<asp:BoundField HeaderText="Active" DataField="prop_active">
<ItemStyle CssClass="gvPropActive" />
</asp:BoundField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lbtnEdit" runat="server" CommandName="EditRecord" Text="Edit"></asp:LinkButton>
<asp:LinkButton ID="lbtnDelete" runat="server" CommandName="Delete" Text="Delete"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lbtnAdd" runat="server" CommandName="AddRecord" Text="Add"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle CssClass="headerPropList"/>
<RowStyle CssClass="gvPropRow" />
</asp:GridView>

Related

Procedure or function has too many arguments specified in FormView and SQL SERVER c#

I have one stored procedure called VideoGalleryDelete . I am using FormView and Gridview to insert, update, show and delete data. VideoGallery is my primary table with PK VideoId and it has a foreign key as CategoryId .
When i click Delete linkButton, its says Procedure or function has too many arguments specified
This is my SP :
ALTER PROCEDURE [dbo].[VideoGalleryDelete]
#VideoId int
AS
BEGIN
DELETE FROM [dbo].[VideoGallery]
WHERE VideoId = #VideoId
END
GridView and its assigned SqlDataSource :
<asp:GridView ID="gvVideo" CssClass="table" runat="server" OnSelectedIndexChanged="gvVideo_SelectedIndexChanged" AutoGenerateColumns="False" DataKeyNames="VideoId,CategoryId" DataSourceID="sdVideoList">
<Columns>
<asp:BoundField DataField="VideoId" Visible="false" HeaderText="VideoId" InsertVisible="False" ReadOnly="True" SortExpression="VideoId" />
<asp:BoundField DataField="VideoLink" HeaderText="Video Link" SortExpression="VideoLink" />
<asp:BoundField DataField="CategoryId" HeaderText="Category Id" SortExpression="CategoryId" />
<asp:TemplateField ItemStyle-CssClass="Center" HeaderStyle-Width="15%">
<ItemTemplate>
<asp:ImageButton ImageUrl="~/images/edit.png" ID="lnkedit" Style="margin-left: 15px" CommandName="Select" runat="server" Width="20px"></asp:ImageButton>
<asp:ImageButton ImageUrl="~/images/delete.png" ID="lnkDelete" CommandName="Delete" Style="margin-left: 15px" runat="server" Width="20px" OnClientClick="return ConfirmDelete();"></asp:ImageButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="sdVideoList" runat="server" ConnectionString="<%$ ConnectionStrings:WebAAERT_DBConnectionString %>" DeleteCommand="VideoGalleryDelete" DeleteCommandType="StoredProcedure" SelectCommand="VideoGallerySelect" SelectCommandType="StoredProcedure">
<DeleteParameters>
<asp:Parameter Name="VideoId" Type="Int32" />
</DeleteParameters>
<SelectParameters>
<asp:Parameter DefaultValue="0" Name="CategoryId" Type="Int32" />
</SelectParameters>
I think you're misusing the DataKeyNames property of the grid view control.This property should ideally contain only the primary key field(s) to identify the current row.Also every single value set on this property will be passed through to the Delete command.
Your delete stored proc takes one parameter but two values are being passed through beacuase of DataKeyNames="VideoId,CategoryId".So you can do what #Chris Flynn suggested or change your grid view to DataKeyNames="VideoId"

'DropDownList1' has a SelectedValue which is invalid because it does not exist in the list of items. Parameter name: value

I have this code that present a gridview that retrieved the data from 2 datasources.
each line present an order details and the last column present the order status.
the order status should be updateable in a dropdownlist .
<asp:GridView runat="server" AutoGenerateColumns="False" DataSourceID="OrderDataSource"
CssClass="DataTables">
<Columns>
<asp:CommandField ShowEditButton="true" />
<asp:BoundField DataField="oID" HeaderText="oId" SortExpression="oId" ReadOnly="true" />
<asp:BoundField DataField="DateOpened" HeaderText="DateOpened" SortExpression="DateOpened"
ReadOnly="true" />
<asp:BoundField DataField="rName" HeaderText="rName" SortExpression="rName" ReadOnly="true" />
<asp:BoundField DataField="DateOfArrival" HeaderText="DateOfArrival" SortExpression="DateOfArrival"
ReadOnly="true" />
<asp:BoundField DataField="Quantity" HeaderText="Quantity" SortExpression="Quantity"
ReadOnly="true" />
<asp:BoundField DataField="sName" HeaderText="sName" SortExpression="sName" ReadOnly="true" />
<asp:TemplateField HeaderText="osName" SortExpression="osName">
<EditItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="StatusDataSource"
DataTextField="osName" DataValueField="osID" SelectedValue='<%# Bind("osName") %>'>
</asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("osName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="OrderDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:igroup9_prodConnectionString %>"
SelectCommand="spGetOrdersListForProject" SelectCommandType="StoredProcedure"
UpdateCommand="Update[Orders] set [osID] =#osID where [oID]=#oID">
<SelectParameters>
<asp:ControlParameter ControlID="ProjectIDHolder" DefaultValue="" Name="ProjectID"
PropertyName="Value" Type="Int32" />
</SelectParameters>
<UpdateParameters>
<asp:Parameter Name="osID" Type="Int32" />
<asp:Parameter Name="oID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="StatusDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:igroup9_prodConnectionString %>"
SelectCommand="spGetOrderStatus" SelectCommandType="StoredProcedure"></asp:SqlDataSource>
The problem is that when i'm trying to edit a column in the gridview i get this error: (after i click the edit button)
Server Error in '/Maestro' Application.
'DropDownList1' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentOutOfRangeException: 'DropDownList1' has a SelectedValue which is invalid because it does not exist in the list of items.
Parameter name: value
Error seems clear to me. The values in the DropDownList don't contain the value that you're trying to set as the selected value. This is probably because the values are from the osID column and the selected value is from the osName column. Whatever the selected value ends up being, it should come from the data source which means you should probably use the same column (or a foreign key relationship).
You should probably change it to...
SelectedValue='<%# Bind("osID") %>'
and make sure that spGetOrdersListForProject returns the osID.

Why is my gridview empty?

I set up an Sqldatasource and a Gridview:
<asp:SqlDataSource ID="DetailsSQLDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:aspnet-WebApplication6-20131007103938ConnectionString1 %>"
SelectCommand="SELECT [ProjectID], [ProjectName], [CreatorID], [Deadline] FROM [tProject] WHERE 1=1"
>
<SelectParameters>
<asp:Parameter Type="String" Name="ProjectID"></asp:Parameter>
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" DataSourceID="DetailsSQLDataSource" AutoGenerateColumns="False" DataKeyNames="ProjectID" OnRowUpdated="GridView1_RowUpdated" OnRowUpdating="GridView1_RowUpdating">
<Columns>
<asp:BoundField DataField="ProjectID" HeaderText="ProjectID" ReadOnly="True" SortExpression="ProjectID"></asp:BoundField>
<asp:BoundField DataField="ProjectName" HeaderText="ProjectName" SortExpression="ProjectName"></asp:BoundField>
<asp:BoundField DataField="CreatorID" HeaderText="CreatorID" SortExpression="CreatorID"></asp:BoundField>
<asp:BoundField DataField="Deadline" HeaderText="Deadline" SortExpression="Deadline"></asp:BoundField>
</Columns>
</asp:GridView>
I have tested the selectcommand, and it returns a table with 4 rows. Yet there is no data to show in the gridview. The codebehind is almost empty and surely doesn't affect these controls. Can it be something with the connection? How can I test that?
Call .DataBind() to actually force the data to be bound to the grid, like this:
GridView1.DataBind();

Editable GridView

I'm trying to allow for editing of the items in a GridView (the DataSource is a database connection). Every example I find has complicated examples implemented within. I'd like to know what the simplest change(s) I need to do are in order to allow for editing of items in the GridView.
In other words, how can I modify the following to allow for editing?
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSourceWS">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="id" HeaderText="id" InsertVisible="False" ReadOnly="True" SortExpression="id" />
<asp:BoundField DataField="NAME" HeaderText="NAME" SortExpression="NAME" />
<asp:BoundField DataField="ACCESS_TO" HeaderText="ACCESS_TO" SortExpression="ACCESS_TO" />
</Columns>
</asp:GridView>
Obviously I'd need to add code as well, but I'm just not sure how to start with this.
EDIT: I thought I'd specified, but I didn't - it's an SQLDataSource.
There are several thing you need to do to enable editing
Assuming that your data source is an SQLDataSource
1) Add a command field to your girdview columns
<asp:CommandField ButtonType="Button" EditText="Edit" ShowEditButton="true"/>
2) Add an update command to your data source
<asp:SqlDataSource ID="SqlDataSourceWS" runat="server"
ConnectionString="<%$ Connection String %>"
SelectCommand=" SELECT COMMAND HERE "
UpdateCommand=" UPDATE COMMAND HERE ">
<UpdateParameters>
<asp:Parameter Name="" />
<asp:Parameter Name="" />
</UpdateParameters>
</asp:SqlDataSource>
For more information on the command field and how to use it you can look at the Microsoft Developer Network Documentation
EDIT
Here is a very simple example of a SQLDatasource that shows how you may update an item
<asp:SqlDataSource ID="sqlMeetings" runat="server"
ConnectionString="<%$ connection %>"
SelectCommand="SELECT [meetingid]
,[groupname]
,[meetingtime]
,[meetingdate]
FROM [DCMS].[dbo].[tbl_meetings] "
UpdateCommand="UPDATE tbl_meetings
SET meetingdate = #meetingdate, meetingtime = #meetingtime
WHERE meetingid = #meetingid">
<UpdateParameters>
<asp:Parameter Name="meetingdate" />
<asp:Parameter Name="meetingtime" />
</UpdateParameters>
</asp:SqlDataSource>
From the example above you can see that I am selecting 3 fields from the data base but only allowing for two to be updated (meetingdate and meetingtime).
To edit the records, the GridView must enter EditMode. The grid changes modes according to the commands it receives, in this case "edit". See the remarks on the gridview page, 'Data Operations' section, for more info.
There are basically three ways to fire the command and enter edit mode on the grid:
Use the AutoGenerateEditButton property on the grid
Use a CommandField with ShowEditButton like the other answer stated
Use a custom TemplateField with a LinkButton inside like this:
<Columns>
...
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" Text="Edit" CommandName="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton runat="server" Text="Update" CommandName="Update" />
<asp:LinkButton runat="server" Text="Cancel" CommandName="Cancel" />
</EditItemTemplate>
</asp:TemplateField>
...
</Columns>
After that, it will depend on which DataSource control you are using. With an EntityDataSource, for instance, all you need to do is set EnableUpdate="true"

Gridview why all visible rows are set to dirty?

I'm using the BulkEditGridView control as discussed http://roohit.com/site/showArc.php?shid=bbb62, and it's perfect for my needs. The problem I'm having is that whenever I save, every visible row (I have paging enabled) gets updated. Stepping through the code I see that grid.DirtyRows.Count is equal to the number of items per page minus 1 when I click the save button.
I can't find where rows are set as dirty. Any suggestions where I can look?
My code-behind has only this:
using System;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Collections;
using System.Data.Common;
public partial class MSDS_MSDS_Admin_GridUpdate : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
gridMSDS.DataKeyNames = new String[] { "id" };
gridMSDS.DataBind();
}
}
}
EDIT: Here is the aspx code.
<%# Page Language="C#" MasterPageFile="~/MSDS/MSDS.master" AutoEventWireup="true" EnableEventValidation="false" CodeFile="GridUpdate.aspx.cs" Inherits="MSDS_MSDS_Admin_GridUpdate" Title="Untitled Page" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<%# Register Assembly="RealWorld.Grids" Namespace="RealWorld.Grids" TagPrefix="cc2" %>
<asp:Content ID="Content1" ContentPlaceHolderID="PageContent" runat="Server">
<br />
<asp:Button ID="btnSave" runat="server" Text="Save" Width="100%" />
<cc2:BulkEditGridView ID="gridMSDS" runat="server" AllowPaging="True" AllowSorting="True"
DataSourceID="sqlData" EnableInsert="False" InsertRowCount="1" PageSize="20"
SaveButtonID="btnSave" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" Visible="false"
ReadOnly="True" SortExpression="ID" />
<asp:BoundField DataField="ChemicalTitle" HeaderText="ChemicalTitle" SortExpression="ChemicalTitle" />
<asp:TemplateField HeaderText="SheetDate" SortExpression="SheetDate">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("SheetDate") %>' Width="85px"></asp:TextBox>
<cc1:CalendarExtender ID="TextBox1_CalendarExtender" runat="server" Enabled="True"
TargetControlID="TextBox1">
</cc1:CalendarExtender>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Eval("SheetDate") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Filename" HeaderText="Filename" SortExpression="Filename" />
<asp:BoundField DataField="Manufacturer" HeaderText="Manufacturer" SortExpression="Manufacturer" />
<asp:BoundField DataField="UsageDept" HeaderText="UsageDept" SortExpression="UsageDept" />
<asp:TemplateField HeaderText="Notes" SortExpression="Notes">
<EditItemTemplate>
<asp:TextBox ID="TextBox5" runat="server" Text='<%# Bind("Notes") %>' TextMode="MultiLine"></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label6" runat="server" Text='<%# Bind("Notes") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Status" SortExpression="Status">
<EditItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server" DataSourceID="sqlStatus" DataTextField="DisplayValue"
DataValueField="Value" SelectedValue='<%# Bind("Status") %>'>
</asp:DropDownList>
<asp:SqlDataSource ID="sqlStatus" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
SelectCommand="getOptionList" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter DefaultValue="msds_Status" Name="ListName" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</EditItemTemplate>
<ItemTemplate>
<asp:DropDownList ID="ddlStatus" runat="server" DataSourceID="sqlStatus" disabled="true"
BackColor="White" DataTextField="DisplayValue" DataValueField="Value" SelectedValue='<%# Bind("Status") %>'>
</asp:DropDownList>
<asp:SqlDataSource ID="sqlStatus" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
SelectCommand="getOptionList" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:Parameter DefaultValue="msds_Status" Name="ListName" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Health" SortExpression="Health">
<EditItemTemplate>
<center>
<asp:TextBox ID="TextBox2" runat="server" Style="text-align: center" Text='<%# Bind("Health") %>'
Width="25px"></asp:TextBox>
</center>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label3" runat="server" Text='<%# Bind("Health") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Fire" SortExpression="Fire">
<EditItemTemplate>
<center>
<asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("Fire") %>' Width="25px"></asp:TextBox></center>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label4" runat="server" Text='<%# Bind("Fire") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Reactivity" SortExpression="Reactivity">
<EditItemTemplate>
<center>
<asp:TextBox ID="TextBox4" runat="server" Text='<%# Bind("Reactivity") %>' Width="25px"></asp:TextBox></center>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label5" runat="server" Text='<%# Bind("Reactivity") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="DateUpdated" HeaderText="DateUpdated" SortExpression="DateUpdated"
ReadOnly="True" />
<asp:BoundField DataField="UpdatedBy" ReadOnly="True" HeaderText="UpdatedBy" SortExpression="UpdatedBy" />
</Columns>
</cc2:BulkEditGridView>
<asp:SqlDataSource ID="sqlData" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
SelectCommand="SELECT [ID], [ChemicalTitle], dbo.dateOnly([SheetDate]) As [SheetDate], [Filename], [Manufacturer], [UsageDept], [Notes], isnull([Status], 4) as [Status], [Health], [Fire], [Reactivity], [DateUpdated], [UpdatedBy] FROM [msds_Sheets] ORDER BY [ChemicalTitle]"
UpdateCommand="msds_UpdateSheet" UpdateCommandType="StoredProcedure">
<UpdateParameters>
<asp:Parameter Name="ID" Type="Int32" />
<asp:Parameter Name="ChemicalTitle" Type="String" />
<asp:Parameter Name="SheetDate" DbType="DateTime" />
<asp:Parameter Name="Filename" Type="String" />
<asp:Parameter Name="Manufacturer" Type="String" />
<asp:Parameter Name="UsageDept" Type="String" />
<asp:Parameter Name="Notes" Type="String" />
<asp:Parameter Name="Status" Type="Int16" />
<asp:Parameter Name="Health" Type="Int16" />
<asp:Parameter Name="Fire" Type="Int16" />
<asp:Parameter Name="Reactivity" Type="Int16" />
<asp:ProfileParameter Name="UpdatedBy" Type="String" PropertyName="Username" />
</UpdateParameters>
</asp:SqlDataSource>
</asp:Content>
Testing Procedure is as follows:
-Load the page.
-Edit something in the first row.
-Click save button.
The code you have posted looks fine. My test code is almost identical to yours, but I cannot produce the unwanted results you are seeing.
The most significant difference between your code and mine is that I don't have the code for your master page. My master page is the default page created by VS 2008. Other than that, the differences are in the SQL and the underlying database. Specifically, I am not using any stored procedures, and I have made reasonable assumptions about the data types involved: the ID is int, Status is smallint, SheetDate is Date, DateUpdated is DateTime, and everything else is varchar.
EDIT: Your SheetDate appears to be just the date portion of an underlying DateTime value from the database. The fact that your query transforms the underlying data value for display purposes is not relevant, because the grid view can't tell that it is getting a modified value. END OF EDIT
Here are a few suggestions for diagnosing the problem:
Test without master page, or with a
very simple dummy master page that is
guaranteed not to have scripts that
interact with the BulkEditGridView.
Since the ToolkitScriptManager is
apparently on your master page, you will
need to either move the script
manager control to the page itself,
or else temporarily get rid of the
CalendarExtender element, which
requires the script manager.
Temporarily replace the Status
template field with a bound data
field, to eliminate possibility of
interaction with the DropDownList.
The drop down list did not cause
problems in my tests, but there may
be subtle differences between your
code and mine.
If neither of these help, then a possible cause is a problem in your
version of the BulkEditGridView.
EDIT - Additional suggestions for diagnosis:
Based on examination of the source code for BulkEditGridView, it appears that the code is properly tracking which rows of the grid are "dirty". Therefore, the most likely cause of a spurious dirty row is that one or more controls in the grid are incorrectly detecting a change to their data content. You can detect this in the debugger, using the source code for BulkEditGridView, rather than the pre-compiled DLL.
Set a breakpoint at the start of HandleRowChanged, the event handler which detects changes in any cell of the grid. By examining the sender parameter of that object in the debugger, you can tell which controls in the grid are undergoing value changes. In particular, you will be able to tell which controls, if any, are incorrectly triggering a value change event.
Once you determine which control(s) are incorrectly reporting that their value has changed, you can focus on why this is happening.
END OF EDIT
Some other suggestions to improve the code are as follows. These will not solve the original problem, but will make the code cleaner:
In all of the template fields, remove the ItemTemplates. They can never be used, since the BulkEditGridView forces every row to be in the edit state.
In the code behind, the BindData()
call is not needed, since the source
data is specified in the declarative
markup, and therefore the grid view
control will automatically bind the
data.
I am not an expert in BulkEditGridView control, but this is what I found at Matt Dotson's blog entry
You may not be able to know that the row has been updated, unless you watch for the change explicitly. First, for each row add a change handler
protected override void InitializeRow(GridViewRow row, DataControlField[] fields)
{
base.InitializeRow(row, fields);
foreach (DataControlFieldCell cell in row.Cells)
{
if (cell.Controls.Count > 0)
{
AddChangedHandlers(cell.Controls);
}
}
}
You can use this snippet
private void AddChangedHandlers(ControlCollection controls)
{
foreach (Control ctrl in controls)
{
if (ctrl is TextBox)
{
((TextBox)ctrl).TextChanged += new EventHandler(this.HandleRowChanged);
}
else if (ctrl is CheckBox)
{
((CheckBox)ctrl).CheckedChanged += new EventHandler(this.HandleRowChanged);
}
else if (ctrl is DropDownList)
{
((DropDownList)ctrl).SelectedIndexChanged += new EventHandler(this.HandleRowChanged);
}
}
}
Then you define a dirty row list and add rows that needs to be updated there (in the event handler)
private List<int> dirtyRows = new List<int>();
void HandleRowChanged(object sender, EventArgs args)
{
GridViewRow row = ((Control) sender).NamingContainer as GridViewRow;
if (null != row && !dirtyRows.Contains(row.RowIndex))
{
dirtyRows.Add(row.RowIndex);
}
}
Finally, to commit changes, iterate through all the dirty rows and save changes
public void Save()
{
foreach (int row in dirtyRows)
{
this.UpdateRow(row, false);
}
dirtyRows.Clear();
}
And here is your ASPX code
<asp:Button runat="server" ID="SaveButton" Text="Save Data" />
<blog:BulkEditGridView runat="server" id="EditableGrid" DataSourceID="AdventureWorks" AutoGenerateColumns="False" DataKeyNames="LocationID" SaveButtonID="SaveButton" >
<Columns>
<asp:BoundField DataField="LocationID" HeaderText="LocationID" InsertVisible="False" ReadOnly="True" SortExpression="LocationID" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="Availability" HeaderText="Availability" SortExpression="Availability" />
<asp:BoundField DataField="CostRate" HeaderText="CostRate" SortExpression="CostRate" />
</Columns>
</blog:BulkEditGridView>

Categories