Rowdeleteing event in Gridview - c#

I have been trying to write this simple logic of deleting a row from the gridview and from the SQL database of the selected row, but keep getting a null reference to cell, which has the primary key [ID] in a field.
Here's my html:
<asp:GridView ID="grvInventoryEdit" runat="server" BackColor="White" onrowdeleting="grvInventoryEdit_RowDeleting"
onrowediting="grvInventoryEdit_RowEditing"
onrowupdating="grvInventoryEdit_RowUpdating">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:CommandField ShowDeleteButton="True" /><asp:TemplateField HeaderText="Id">
<ItemTemplate>
<%#Eval("No")%>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>........ </Columns> </asp:GridView>
And my back-end code for rowdeleting event is :
protected void grvInventoryEdit_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
TextBox id = (TextBox)grvInventoryEdit.Rows[e.RowIndex].FindControl("txtEditNo");
Asset asset = db.Assets.Single(a => a.No == Convert.ToInt32(id));
db.Assets.DeleteOnSubmit(asset);
db.SubmitChanges();
binddata();
}
and when the event fires, this is what i am seeing while debugging:
I am not sure why i am getting a null value ,though, there is a value for that cell.
Could you tell me what i am doing wrong ?
Regards,

Might be it is due to the readonly property of textbox, not suer.
If you want to use the image button for edit and delete then use
protected void ibtnDelete_Click(object sender, ImageClickEventArgs e)
{
GridViewRow gvRow = (GridViewRow)((ImageButton)sender).NamingContainer;
Int32 UserId = Convert.ToInt32(gvUsers.DataKeys[gvRow.RowIndex].Value);
// delete and hide the row from grid view
if (DeleteUserByID(UserId))
gvRow.Visible = false;
}
For complete code see

You are passing TextBox object instead instead of Text property of TextBox
Asset asset = db.Assets.Single(x=>x.No == Convert.ToInt32(id.Text));
and your TextBox is also coming null means it's unable to find it in GridView, try like this:
TextBox id = e.Row.FindControl("txtEditNo");
Also see this CodeProject article to understand how to use ItemTemplate and EditItemTemplate

why are you adding a second commandfield instead of just enabling the delete button on the existing one.
if you are using a command field you should be supplying an compatible datasource that provides Delete functionality
if you're "rolling your own" delete functionality then just use a regular Button control and supply a CommandName and CommandArgument, such as CommandName="MyDelete" CommandArgument=<row number> where <row number> is supplied via GridView RowDataBound() event.
Regardless of how you choose to implement Delete you should be placing the key field in the GridView DataKeys Property and not as a field within each row. This will make obtaining the PK far easier than what you are trying to do

I guess, in my HTML, i have only the value that's bound to the item, is being displayed, and there are no textboxes in my <ItemTemplate>, hence, it pulls null value. Whereas, in my <EditItemTemplate> there is a textbox, which can pull the value from the cell.
So I changed my HTML to this:
<asp:TemplateField HeaderText="Id">
<ItemTemplate>`<asp:label runat="server" ID="lblEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="txtEditNo" ReadOnly="True" Text='<%#Eval("No")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
and no change in my codebehind, and this resolved the issue.

Related

Problem with being able to access certain elements in GridView -> TemplateField -> EditItemTemplate

I have this problem with being able to access certain elements in
GridView -> TemplateField -> EditItemTemplate.
To be more clear, I have textbox and button
(in GridView -> TemplateField -> EditItemTemplate) and only one of them must be visible depending on operation. If I want to edit, button must be visible and if I want to add new user then textbox must be visible. I have added my aspx code for you to check and also C# code-behind. The method in C# code is the one which gets called immidiately when I press "Edit" button which lets to edit account details and permissions for one user. And I want that this method would decide whenever to show textbox or button (I have IsUserInsertMode property for that.)
I would be really grateful for someone who would help me out with this.
<asp:GridView CssClass="grid" ID="gridUsers" runat="server"
AutoGenerateColumns="False" DataKeyNames="id"
DataSourceID="dsrcUserList" GridLines="None"
OnRowCommand="gridUsers_RowCommand" OnDataBound="gridUsers_DataBound"
OnRowUpdating="gridUsers_Updating" OnRowUpdated="gridUsers_Updated" EnableModelValidation="True">
<Columns>
<asp:TemplateField HeaderText="Password" ItemStyle-HorizontalAlign="center" ItemStyle-Width="80px">
<ItemTemplate>
*******
</ItemTemplate>
<EditItemTemplate>
**NEED REFERENCES TO THESE TWO ITEMS IN ORDER TO SET THEIR VISIBILITY**
<asp:Button ID="btnEditPassword" Text="Change" runat="server" CausesValidation="false" OnClick="btnEditPassword_Click" Visible="false"/>
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" Text='<%# Bind("Password") %>' Width="74px" MaxLength="50" Visible="true" />
</EditItemTemplate>
</asp:TemplateField>
**LOTS OF CHECKBOXES LIKE THOSE**
<asp:CheckBoxField DataField="AccessTowsRelease" HeaderText="TowsRelease" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessTowsView" HeaderText="TowsView" ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
<asp:CheckBoxField DataField="AccessSMS" HeaderText="SMS"
ItemStyle-HorizontalAlign="Center">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:CheckBoxField>
**MY EDIT BUTTON**
<asp:CommandField ButtonType="Link"
ShowEditButton="true" EditText="Edit"
CancelText="Cancel" UpdateText="Save" />
</Columns>
</asp:GridView>
C# code-behind (I have added some of the stuff that I have tried)
// this is called when I press some button which lets me to edit one user data including password
// but when I want to change password, there should be button which would redirect to different
// window to do the password change procedure.
// And when I want to add new user there should be textbox for password, not the button.
protected void gridUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
//Found the way to get the index of current row (represents one row of information which is visible for the client in browser)
int rowIndex = Convert.ToInt32(e.CommandArgument);
//if those would be working I wouldn't be here asking for help
btnEditPassword.Visible = true;
txtPassword.Visible = false;
//Can't cast 'System.Web.UI.WebControls.GridView' to type 'System.Web.UI.WebControls.GridViewRow'
Button btnEditPassword = (Button)((GridViewRow)sender).FindControl("btnEditPassword");
//every attempt to use FindControl gets me null
Button btnEditPassword = (Button)this.gridUsers.Rows[rowIndex].FindControl("btnEditPassword");
// my way to check if it works - if its null then I do can't anything (prints to browser console).
if (btnEditPassword != null) Response.Write("<script>console.log('not null')</script>");
else Response.Write("<script>console.log('null')</script>");
}
The RowCommand-event is raised too early for your case. It's raised before the row is going into edit mode, that's why you don't find the controls of your edit-item-template.
First change your markup to handle the RowDataBound-event:
<asp:GridView ... OnRowDataBound="gridUsers_OnRowDataBound" ...>
Then handle this in the OnRowDataBound-event like this:
protected void gridUsers_OnRowDataBound(object sender, GridViewRowEventArgs e) {
// check if row is in edit state
if ((e.Row.RowState == DataControlRowState.Edit) || (e.Row.RowState == (DataControlRowState.Alternate | DataControlRowState.Edit))) {
// look for the control in the row
Button btnEditPassword = (Button)e.Row.FindControl("btnEditPassword");
}
}

Show editable Gridview when value is selected from dropdown

I have created a bulk edit gridview using Itemtemplate for each column. Label for non-edit mode, Textbox for edit mode. But this works only if the structure of gridview is known(Defining templates in asp).
<asp:TemplateField HeaderText="Name" ConvertEmptyStringToNull="True">
<ItemTemplate>
<asp:Label ID="lblName" Visible='<%# !(bool) IsInEditMode %>' runat="server" Text='<%# Eval("name") %>' />
<asp:TextBox ID="txtName" ControlStyle-CssClass="wide" Visible='<%# IsInEditMode %>'
runat="server" Text='<%# Eval("name") %>' />
</ItemTemplate>
</asp:TemplateField>
Now, what I am trying to achieve is when the user selects a dropdown value, the sql query is fired and it returns result. And this result is shown in gridview. But the problem arises because the number of columns in the result for each selected value from dropdown may vary. And i want to make the gridview as editable(or read-only). This requires two templates to be defined for each column.
So i want to know how this can be done dynamically i.e defining templates depending on number of columns returned by sql.
First off, you could trigger the query and following code with this event.
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
//insert code
}
For the issue of different templates, I might suggest using two GridViews. I've done this where I have two separate sets of results. If they choose a dropdownItem, it hides GridView1 and shows GridView2 (while querying GridView2.SqlDataSource).
Now are you querying different SQL Tables based on dropdown? Or are they querying from the same place?

how to find out the selected row in a gridview

I am doing a project in .net with c#. in that there is a registration form of new users into the site. admin should approve the registration. for that I'm using a GridView. How to find out the selected row in the grid view?
Use the GridView.SelectedRow property.
Alternatively, you can get the index of the selected row with the GridView.SelectedIndex property.
are you perhaps referring to a DATAGRIDVIEW?
if so, to find the content of a certain column of the selected row
datagridviewname.item(0, datagridviewname.currentrow.index).value
where 0 = first column of your datagrid
Use following gridview property>
gvTradeFile.SelectedRows[0].Cells[10].Value.ToString();
Hope this will help you.
Normally I use RowCommand for this type of thing:
<asp:GridView runat="server" id="gvUsers" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="username" HeaderText="Username" />
<asp:BoundField DataField="dateregistered" HeaderText="Date" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" id="lnkApprove" CommandName="Approve" CommandArgument='<%# Eval("userid") %>' Text="Approve"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" id="lnkDeny" CommandName="Deny" CommandArgument='<%# Eval("userid") %>' Text="Deny"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now you need to pass instructions through on RowCommand...
private void gvUsers_RowCommand(Object sender, GridViewCommandEventArgs e)
{
switch (e.CommandName)
{
case "Approve":
// Executes code to update the users table,
// setting the approved flag to true
// Usage: ApproveUser(integer userid);
ApproveUser(e.CommandArgument);
break;
case else:
// do whatever if the user registration wasn't approved
break;
}
}
The switch is a good idea in case you need to do a few things with the data here. It evaluates the primary key value for the row (in this case, that's the value of the userid column in the database) for the selected row (automatically determined when you click the link) along with the CommandName to tell it what to do with that information.
Hope this helps.

Insert extra custom fields from DetailsView

I am using a DetailsView control (C# 4.0) to add a record with an EntityDataSource control. There are some fields that need to be added which I do not want to be visible in the DetailsView control - such as DateAdded and UserId - these fields should be added automatically.
<asp:EntityDataSource ID="edsTasks" runat="server"
ContextTypeName="EKIMV2_MasterModel.EKIMV2_MasterEntities"
EnableFlattening="False" EnableInsert="True"
EntitySetName="tasks" ConnectionString="name=EKIMV2_MasterEntities"
DefaultContainerName="EKIMV2_MasterEntities">
</asp:EntityDataSource>
<asp:DetailsView ID="DetailsView1" runat="server" Height="50px" Width="125px"
DataSourceID="edsTasks" DefaultMode="Insert"
AutoGenerateRows="False" DataKeyNames="task_id"
oniteminserted="DetailsView1_ItemInserted"
oniteminserting="DetailsView1_ItemInserting">
<Fields>
<asp:BoundField DataField="task_name" HeaderText="task_name"
SortExpression="task_name" />
<asp:BoundField DataField="task_desc" HeaderText="task_desc"
SortExpression="task_desc" />
<asp:TemplateField HeaderText="assigned_to" SortExpression="assigned_to">
<InsertItemTemplate>
<asp:DropDownList ID="ddlUsers" runat="server" DataSourceID="edsUsers" DataTextField="UserName" DataValueField="UserId"></asp:DropDownList>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("assigned_to") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowCancelButton="False"
ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
As you can see above there is no DateAdded field. I want to automatically set this value to today's date. The user doesn't need to add the value or see the field at all. There are other fields that I want to set automatically, but without getting into too much detail I think the DateAdded field gives a good example.
I figure I need to somehow add the extra fields during the ItemInserting event, but I don't know where to start.
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
}
I've read elsewhere that maybe I need to keep the extra fields in the DetailsView but hide them? Is that right, it doesn't seem like the right thing to do.
So is it possible to add values to fields that are not actually in the DetailsView?
So the answer lies in hiding the fields in the DetailsView by converting them to TemplateFields then using a HiddenField within the template.
You then need to handle the DetailsView1_ItemInserting() event like so:
protected void DetailsView1_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
e.Values["date_submitted"] = DateTime.Now.ToShortDateString();
}
The event receives DetailsViewInsertEvenrArgs ("e") which contains a dictionary object called Values. Values contains the data that is passed back to your datasource control (an EntityDataSource) in my case.

ASP.NET 2.0 Gridview CheckBox column

I have a GridView that displays data on three columns. On the third column I have a CheckBox. I have two things that I need to achieve
CheckBox will be checked based on the column value (1,0)
If it is checked the rest of the two columns should display #### However the data for the two columns should remain in the database.
How can this be achieved?
Can I find the CheckBox on RowDataBound event and check the value and make the CheckBox checked and unchecked? How about making the other columns ####?
NEW Comments:
string str = ((System.Data.DataRowView)(e.Row.DataItem)).Row.ItemArray[2].ToString();
this helps to set the checkbox checked or not.
if checked is true I am trying the following.
((System.Data.DataRowView)(e.Row.DataItem)).Row.ItemArray[0] = "#####";
((System.Data.DataRowView)(e.Row.DataItem)).Row.ItemArray[1] = "#####";
((System.Data.DataRowView)(e.Row.DataItem)).Row.AcceptChanges();
It is displaying the gridview checkbox as checked but the column value is not changed to "####"
You can turn your item columns into TemplateColumns and do the following which will localize your code to the control level and you don't have to worry about all the searching. I pefer to never use the built in column types because there are usually future enhancements that require changing the columns to TemplateColumns anyways. It also gives you a lot of flexibiltiy on useage.
Here is an example:
<asp:GridView ID="grdYourGrid" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField HeaderText="YourField1">
<ItemTemplate>
<asp:Literal runat="server" ID="ltYourField1"
OnDataBinding="ltYourField1_DataBinding" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="YourField2">
<ItemTemplate>
<asp:Literal runat="server" ID="ltYourField2"
OnDataBinding="ltYourField2_DataBinding" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="YourCheckBoxField">
<ItemTemplate>
<asp:CheckBox runat="server" ID="chkYourCheckBoxField"
OnDataBinding="chkYourCheckBoxField_DataBinding" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Then in your codebehind implement each control's OnDataBinding:
protected void ltYourField1_DataBinding(object sender, System.EventArgs e)
{
Literal lt = (Literal)(sender);
lt.Text = (bool)(Eval("YourCheckBoxField")) ?
"##########" : Eval("YourField1");
}
protected void ltYourField2_DataBinding(object sender, System.EventArgs e)
{
Literal lt = (Literal)(sender);
lt.Text = (bool)(Eval("YourCheckBoxField")) ?
"##########" : Eval("YourField2");
}
protected void chkYourCheckBoxField_DataBinding(object sender, System.EventArgs e)
{
CheckBox chk = (CheckBox)(sender);
chk.Checked = (bool)(Eval("YourCheckBoxField"));
}
The advantages to doing it this way is your could replace code easily as it is all isolated and has no 'searching' for expected controls. I very rarely use the RowDataBound event because it makes you have to write specific code to look for the controls and it makes more sense to me to have the code localized to the control. If someone changes something they know there are ONLY affecting that one control instead of everything on the row possibly as a side effect. You could also use the <%# method and do the Evals right in the markup but I personally prefer to never have any code in the aspx markup at all.

Categories

Resources